]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
initial support for user clipping plane in dpsoftrast
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
121
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130
131 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
132 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
133
134 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
139
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
152
153 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
159 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
160 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
161 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
162 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
163 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
164 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
168
169 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
170 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
171 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
172 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
173 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
174 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
175
176 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
177 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
178 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
179 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
180
181 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
182 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
183 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
184 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
185 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
186 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
187 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
188
189 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
190 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
191 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
192 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
193 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
194 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
195 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
196 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
197 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
198 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
199
200 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
201
202 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
203
204 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
205
206 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
207 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
208 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
209 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
210 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
211 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
212 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
213 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
214 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
215
216 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
217 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
218
219 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
220
221 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
222
223 extern cvar_t v_glslgamma;
224
225 extern qboolean v_flipped_state;
226
227 static struct r_bloomstate_s
228 {
229         qboolean enabled;
230         qboolean hdr;
231
232         int bloomwidth, bloomheight;
233
234         textype_t texturetype;
235         int viewfbo; // used to check if r_viewfbo cvar has changed
236
237         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
238         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
239         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
240
241         int screentexturewidth, screentextureheight;
242         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
243
244         int bloomtexturewidth, bloomtextureheight;
245         rtexture_t *texture_bloom;
246
247         // arrays for rendering the screen passes
248         float screentexcoord2f[8];
249         float bloomtexcoord2f[8];
250         float offsettexcoord2f[8];
251
252         r_viewport_t viewport;
253 }
254 r_bloomstate;
255
256 r_waterstate_t r_waterstate;
257
258 /// shadow volume bsp struct with automatically growing nodes buffer
259 svbsp_t r_svbsp;
260
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
274
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
277 {
278         char basename[64];
279         rtexture_t *texture;
280 }
281 cubemapinfo_t;
282
283 int r_texture_numcubemaps;
284 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
285
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
289
290 typedef struct r_qwskincache_s
291 {
292         char name[MAX_QPATH];
293         skinframe_t *skinframe;
294 }
295 r_qwskincache_t;
296
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
299
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
304 {
305         0, 0, 0,
306         1, 0, 0,
307         1, 1, 0,
308         0, 1, 0
309 };
310 const float r_d3dscreenvertex3f[12] =
311 {
312         0, 1, 0,
313         1, 1, 0,
314         1, 0, 0,
315         0, 0, 0
316 };
317
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
319 {
320         int i;
321         for (i = 0;i < verts;i++)
322         {
323                 out[0] = in[0] * r;
324                 out[1] = in[1] * g;
325                 out[2] = in[2] * b;
326                 out[3] = in[3];
327                 in += 4;
328                 out += 4;
329         }
330 }
331
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
333 {
334         int i;
335         for (i = 0;i < verts;i++)
336         {
337                 out[0] = r;
338                 out[1] = g;
339                 out[2] = b;
340                 out[3] = a;
341                 out += 4;
342         }
343 }
344
345 // FIXME: move this to client?
346 void FOG_clear(void)
347 {
348         if (gamemode == GAME_NEHAHRA)
349         {
350                 Cvar_Set("gl_fogenable", "0");
351                 Cvar_Set("gl_fogdensity", "0.2");
352                 Cvar_Set("gl_fogred", "0.3");
353                 Cvar_Set("gl_foggreen", "0.3");
354                 Cvar_Set("gl_fogblue", "0.3");
355         }
356         r_refdef.fog_density = 0;
357         r_refdef.fog_red = 0;
358         r_refdef.fog_green = 0;
359         r_refdef.fog_blue = 0;
360         r_refdef.fog_alpha = 1;
361         r_refdef.fog_start = 0;
362         r_refdef.fog_end = 16384;
363         r_refdef.fog_height = 1<<30;
364         r_refdef.fog_fadedepth = 128;
365         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
366 }
367
368 static void R_BuildBlankTextures(void)
369 {
370         unsigned char data[4];
371         data[2] = 128; // normal X
372         data[1] = 128; // normal Y
373         data[0] = 255; // normal Z
374         data[3] = 128; // height
375         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 255;
377         data[1] = 255;
378         data[2] = 255;
379         data[3] = 255;
380         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 128;
382         data[1] = 128;
383         data[2] = 128;
384         data[3] = 255;
385         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 0;
387         data[1] = 0;
388         data[2] = 0;
389         data[3] = 255;
390         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 }
392
393 static void R_BuildNoTexture(void)
394 {
395         int x, y;
396         unsigned char pix[16][16][4];
397         // this makes a light grey/dark grey checkerboard texture
398         for (y = 0;y < 16;y++)
399         {
400                 for (x = 0;x < 16;x++)
401                 {
402                         if ((y < 8) ^ (x < 8))
403                         {
404                                 pix[y][x][0] = 128;
405                                 pix[y][x][1] = 128;
406                                 pix[y][x][2] = 128;
407                                 pix[y][x][3] = 255;
408                         }
409                         else
410                         {
411                                 pix[y][x][0] = 64;
412                                 pix[y][x][1] = 64;
413                                 pix[y][x][2] = 64;
414                                 pix[y][x][3] = 255;
415                         }
416                 }
417         }
418         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
419 }
420
421 static void R_BuildWhiteCube(void)
422 {
423         unsigned char data[6*1*1*4];
424         memset(data, 255, sizeof(data));
425         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
426 }
427
428 static void R_BuildNormalizationCube(void)
429 {
430         int x, y, side;
431         vec3_t v;
432         vec_t s, t, intensity;
433 #define NORMSIZE 64
434         unsigned char *data;
435         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436         for (side = 0;side < 6;side++)
437         {
438                 for (y = 0;y < NORMSIZE;y++)
439                 {
440                         for (x = 0;x < NORMSIZE;x++)
441                         {
442                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 switch(side)
445                                 {
446                                 default:
447                                 case 0:
448                                         v[0] = 1;
449                                         v[1] = -t;
450                                         v[2] = -s;
451                                         break;
452                                 case 1:
453                                         v[0] = -1;
454                                         v[1] = -t;
455                                         v[2] = s;
456                                         break;
457                                 case 2:
458                                         v[0] = s;
459                                         v[1] = 1;
460                                         v[2] = t;
461                                         break;
462                                 case 3:
463                                         v[0] = s;
464                                         v[1] = -1;
465                                         v[2] = -t;
466                                         break;
467                                 case 4:
468                                         v[0] = s;
469                                         v[1] = -t;
470                                         v[2] = 1;
471                                         break;
472                                 case 5:
473                                         v[0] = -s;
474                                         v[1] = -t;
475                                         v[2] = -1;
476                                         break;
477                                 }
478                                 intensity = 127.0f / sqrt(DotProduct(v, v));
479                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482                                 data[((side*64+y)*64+x)*4+3] = 255;
483                         }
484                 }
485         }
486         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
487         Mem_Free(data);
488 }
489
490 static void R_BuildFogTexture(void)
491 {
492         int x, b;
493 #define FOGWIDTH 256
494         unsigned char data1[FOGWIDTH][4];
495         //unsigned char data2[FOGWIDTH][4];
496         double d, r, alpha;
497
498         r_refdef.fogmasktable_start = r_refdef.fog_start;
499         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500         r_refdef.fogmasktable_range = r_refdef.fogrange;
501         r_refdef.fogmasktable_density = r_refdef.fog_density;
502
503         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
505         {
506                 d = (x * r - r_refdef.fogmasktable_start);
507                 if(developer_extra.integer)
508                         Con_DPrintf("%f ", d);
509                 d = max(0, d);
510                 if (r_fog_exp2.integer)
511                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
512                 else
513                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514                 if(developer_extra.integer)
515                         Con_DPrintf(" : %f ", alpha);
516                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517                 if(developer_extra.integer)
518                         Con_DPrintf(" = %f\n", alpha);
519                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
520         }
521
522         for (x = 0;x < FOGWIDTH;x++)
523         {
524                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
525                 data1[x][0] = b;
526                 data1[x][1] = b;
527                 data1[x][2] = b;
528                 data1[x][3] = 255;
529                 //data2[x][0] = 255 - b;
530                 //data2[x][1] = 255 - b;
531                 //data2[x][2] = 255 - b;
532                 //data2[x][3] = 255;
533         }
534         if (r_texture_fogattenuation)
535         {
536                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538         }
539         else
540         {
541                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
543         }
544 }
545
546 static void R_BuildFogHeightTexture(void)
547 {
548         unsigned char *inpixels;
549         int size;
550         int x;
551         int y;
552         int j;
553         float c[4];
554         float f;
555         inpixels = NULL;
556         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557         if (r_refdef.fogheighttexturename[0])
558                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
559         if (!inpixels)
560         {
561                 r_refdef.fog_height_tablesize = 0;
562                 if (r_texture_fogheighttexture)
563                         R_FreeTexture(r_texture_fogheighttexture);
564                 r_texture_fogheighttexture = NULL;
565                 if (r_refdef.fog_height_table2d)
566                         Mem_Free(r_refdef.fog_height_table2d);
567                 r_refdef.fog_height_table2d = NULL;
568                 if (r_refdef.fog_height_table1d)
569                         Mem_Free(r_refdef.fog_height_table1d);
570                 r_refdef.fog_height_table1d = NULL;
571                 return;
572         }
573         size = image_width;
574         r_refdef.fog_height_tablesize = size;
575         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
578         Mem_Free(inpixels);
579         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
580         // average fog color table accounting for every fog layer between a point
581         // and the camera.  (Note: attenuation is handled separately!)
582         for (y = 0;y < size;y++)
583         {
584                 for (x = 0;x < size;x++)
585                 {
586                         Vector4Clear(c);
587                         f = 0;
588                         if (x < y)
589                         {
590                                 for (j = x;j <= y;j++)
591                                 {
592                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
593                                         f++;
594                                 }
595                         }
596                         else
597                         {
598                                 for (j = x;j >= y;j--)
599                                 {
600                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601                                         f++;
602                                 }
603                         }
604                         f = 1.0f / f;
605                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
609                 }
610         }
611         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
612 }
613
614 //=======================================================================================================================================================
615
616 static const char *builtinshaderstring =
617 #include "shader_glsl.h"
618 ;
619
620 const char *builtinhlslshaderstring =
621 #include "shader_hlsl.h"
622 ;
623
624 char *glslshaderstring = NULL;
625 char *hlslshaderstring = NULL;
626
627 //=======================================================================================================================================================
628
629 typedef struct shaderpermutationinfo_s
630 {
631         const char *pretext;
632         const char *name;
633 }
634 shaderpermutationinfo_t;
635
636 typedef struct shadermodeinfo_s
637 {
638         const char *vertexfilename;
639         const char *geometryfilename;
640         const char *fragmentfilename;
641         const char *pretext;
642         const char *name;
643 }
644 shadermodeinfo_t;
645
646 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
647 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
648 {
649         {"#define USEDIFFUSE\n", " diffuse"},
650         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
651         {"#define USEVIEWTINT\n", " viewtint"},
652         {"#define USECOLORMAPPING\n", " colormapping"},
653         {"#define USESATURATION\n", " saturation"},
654         {"#define USEFOGINSIDE\n", " foginside"},
655         {"#define USEFOGOUTSIDE\n", " fogoutside"},
656         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
657         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
658         {"#define USEGAMMARAMPS\n", " gammaramps"},
659         {"#define USECUBEFILTER\n", " cubefilter"},
660         {"#define USEGLOW\n", " glow"},
661         {"#define USEBLOOM\n", " bloom"},
662         {"#define USESPECULAR\n", " specular"},
663         {"#define USEPOSTPROCESSING\n", " postprocessing"},
664         {"#define USEREFLECTION\n", " reflection"},
665         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
666         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
667         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
668         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
669         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
670         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
671         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
672         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
673         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
674         {"#define USEALPHAKILL\n", " alphakill"},
675         {"#define USEREFLECTCUBE\n", " reflectcube"},
676         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
677         {"#define USEBOUNCEGRID\n", " bouncegrid"},
678         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
679 };
680
681 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
682 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
683 {
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
700 };
701
702 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
703 {
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
720 };
721
722 struct r_glsl_permutation_s;
723 typedef struct r_glsl_permutation_s
724 {
725         /// hash lookup data
726         struct r_glsl_permutation_s *hashnext;
727         unsigned int mode;
728         unsigned int permutation;
729
730         /// indicates if we have tried compiling this permutation already
731         qboolean compiled;
732         /// 0 if compilation failed
733         int program;
734         // texture units assigned to each detected uniform
735         int tex_Texture_First;
736         int tex_Texture_Second;
737         int tex_Texture_GammaRamps;
738         int tex_Texture_Normal;
739         int tex_Texture_Color;
740         int tex_Texture_Gloss;
741         int tex_Texture_Glow;
742         int tex_Texture_SecondaryNormal;
743         int tex_Texture_SecondaryColor;
744         int tex_Texture_SecondaryGloss;
745         int tex_Texture_SecondaryGlow;
746         int tex_Texture_Pants;
747         int tex_Texture_Shirt;
748         int tex_Texture_FogHeightTexture;
749         int tex_Texture_FogMask;
750         int tex_Texture_Lightmap;
751         int tex_Texture_Deluxemap;
752         int tex_Texture_Attenuation;
753         int tex_Texture_Cube;
754         int tex_Texture_Refraction;
755         int tex_Texture_Reflection;
756         int tex_Texture_ShadowMap2D;
757         int tex_Texture_CubeProjection;
758         int tex_Texture_ScreenDepth;
759         int tex_Texture_ScreenNormalMap;
760         int tex_Texture_ScreenDiffuse;
761         int tex_Texture_ScreenSpecular;
762         int tex_Texture_ReflectMask;
763         int tex_Texture_ReflectCube;
764         int tex_Texture_BounceGrid;
765         /// locations of detected uniforms in program object, or -1 if not found
766         int loc_Texture_First;
767         int loc_Texture_Second;
768         int loc_Texture_GammaRamps;
769         int loc_Texture_Normal;
770         int loc_Texture_Color;
771         int loc_Texture_Gloss;
772         int loc_Texture_Glow;
773         int loc_Texture_SecondaryNormal;
774         int loc_Texture_SecondaryColor;
775         int loc_Texture_SecondaryGloss;
776         int loc_Texture_SecondaryGlow;
777         int loc_Texture_Pants;
778         int loc_Texture_Shirt;
779         int loc_Texture_FogHeightTexture;
780         int loc_Texture_FogMask;
781         int loc_Texture_Lightmap;
782         int loc_Texture_Deluxemap;
783         int loc_Texture_Attenuation;
784         int loc_Texture_Cube;
785         int loc_Texture_Refraction;
786         int loc_Texture_Reflection;
787         int loc_Texture_ShadowMap2D;
788         int loc_Texture_CubeProjection;
789         int loc_Texture_ScreenDepth;
790         int loc_Texture_ScreenNormalMap;
791         int loc_Texture_ScreenDiffuse;
792         int loc_Texture_ScreenSpecular;
793         int loc_Texture_ReflectMask;
794         int loc_Texture_ReflectCube;
795         int loc_Texture_BounceGrid;
796         int loc_Alpha;
797         int loc_BloomBlur_Parameters;
798         int loc_ClientTime;
799         int loc_Color_Ambient;
800         int loc_Color_Diffuse;
801         int loc_Color_Specular;
802         int loc_Color_Glow;
803         int loc_Color_Pants;
804         int loc_Color_Shirt;
805         int loc_DeferredColor_Ambient;
806         int loc_DeferredColor_Diffuse;
807         int loc_DeferredColor_Specular;
808         int loc_DeferredMod_Diffuse;
809         int loc_DeferredMod_Specular;
810         int loc_DistortScaleRefractReflect;
811         int loc_EyePosition;
812         int loc_FogColor;
813         int loc_FogHeightFade;
814         int loc_FogPlane;
815         int loc_FogPlaneViewDist;
816         int loc_FogRangeRecip;
817         int loc_LightColor;
818         int loc_LightDir;
819         int loc_LightPosition;
820         int loc_OffsetMapping_ScaleSteps;
821         int loc_PixelSize;
822         int loc_ReflectColor;
823         int loc_ReflectFactor;
824         int loc_ReflectOffset;
825         int loc_RefractColor;
826         int loc_Saturation;
827         int loc_ScreenCenterRefractReflect;
828         int loc_ScreenScaleRefractReflect;
829         int loc_ScreenToDepth;
830         int loc_ShadowMap_Parameters;
831         int loc_ShadowMap_TextureScale;
832         int loc_SpecularPower;
833         int loc_UserVec1;
834         int loc_UserVec2;
835         int loc_UserVec3;
836         int loc_UserVec4;
837         int loc_ViewTintColor;
838         int loc_ViewToLight;
839         int loc_ModelToLight;
840         int loc_TexMatrix;
841         int loc_BackgroundTexMatrix;
842         int loc_ModelViewProjectionMatrix;
843         int loc_ModelViewMatrix;
844         int loc_PixelToScreenTexCoord;
845         int loc_ModelToReflectCube;
846         int loc_ShadowMapMatrix;
847         int loc_BloomColorSubtract;
848         int loc_NormalmapScrollBlend;
849         int loc_BounceGridMatrix;
850         int loc_BounceGridIntensity;
851 }
852 r_glsl_permutation_t;
853
854 #define SHADERPERMUTATION_HASHSIZE 256
855
856
857 // non-degradable "lightweight" shader parameters to keep the permutations simpler
858 // these can NOT degrade! only use for simple stuff
859 enum
860 {
861         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
862         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
863         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
864         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
865         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
866         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
867         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
868 };
869 #define SHADERSTATICPARMS_COUNT 7
870
871 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
872 static int shaderstaticparms_count = 0;
873
874 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
875 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
876 qboolean R_CompileShader_CheckStaticParms(void)
877 {
878         static int r_compileshader_staticparms_save[1];
879         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
880         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
881
882         // detect all
883         if (r_glsl_saturation_redcompensate.integer)
884                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
885         if (r_glsl_vertextextureblend_usebothalphas.integer)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
887         if (r_shadow_glossexact.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
889         if (r_glsl_postprocess.integer)
890         {
891                 if (r_glsl_postprocess_uservec1_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
893                 if (r_glsl_postprocess_uservec2_enable.integer)
894                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
895                 if (r_glsl_postprocess_uservec3_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
897                 if (r_glsl_postprocess_uservec4_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
899         }
900         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
901 }
902
903 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
904         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
905                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
906         else \
907                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
908 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
909 {
910         shaderstaticparms_count = 0;
911
912         // emit all
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
920 }
921
922 /// information about each possible shader permutation
923 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
924 /// currently selected permutation
925 r_glsl_permutation_t *r_glsl_permutation;
926 /// storage for permutations linked in the hash table
927 memexpandablearray_t r_glsl_permutationarray;
928
929 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
930 {
931         //unsigned int hashdepth = 0;
932         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
933         r_glsl_permutation_t *p;
934         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
935         {
936                 if (p->mode == mode && p->permutation == permutation)
937                 {
938                         //if (hashdepth > 10)
939                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
940                         return p;
941                 }
942                 //hashdepth++;
943         }
944         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
945         p->mode = mode;
946         p->permutation = permutation;
947         p->hashnext = r_glsl_permutationhash[mode][hashindex];
948         r_glsl_permutationhash[mode][hashindex] = p;
949         //if (hashdepth > 10)
950         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
951         return p;
952 }
953
954 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
955 {
956         char *shaderstring;
957         if (!filename || !filename[0])
958                 return NULL;
959         if (!strcmp(filename, "glsl/default.glsl"))
960         {
961                 if (!glslshaderstring)
962                 {
963                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
964                         if (glslshaderstring)
965                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
966                         else
967                                 glslshaderstring = (char *)builtinshaderstring;
968                 }
969                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
970                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
971                 return shaderstring;
972         }
973         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
974         if (shaderstring)
975         {
976                 if (printfromdisknotice)
977                         Con_DPrintf("from disk %s... ", filename);
978                 return shaderstring;
979         }
980         return shaderstring;
981 }
982
983 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
984 {
985         int i;
986         int sampler;
987         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
988         char *vertexstring, *geometrystring, *fragmentstring;
989         char permutationname[256];
990         int vertstrings_count = 0;
991         int geomstrings_count = 0;
992         int fragstrings_count = 0;
993         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
994         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996
997         if (p->compiled)
998                 return;
999         p->compiled = true;
1000         p->program = 0;
1001
1002         permutationname[0] = 0;
1003         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1004         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1005         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1006
1007         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1008
1009         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1010         if(vid.support.gl20shaders130)
1011         {
1012                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1013                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1014                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1015                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1016                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1017                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1018         }
1019
1020         // the first pretext is which type of shader to compile as
1021         // (later these will all be bound together as a program object)
1022         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1023         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1024         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1025
1026         // the second pretext is the mode (for example a light source)
1027         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1028         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1029         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1030         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1031
1032         // now add all the permutation pretexts
1033         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1034         {
1035                 if (permutation & (1<<i))
1036                 {
1037                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1038                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1039                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1040                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1041                 }
1042                 else
1043                 {
1044                         // keep line numbers correct
1045                         vertstrings_list[vertstrings_count++] = "\n";
1046                         geomstrings_list[geomstrings_count++] = "\n";
1047                         fragstrings_list[fragstrings_count++] = "\n";
1048                 }
1049         }
1050
1051         // add static parms
1052         R_CompileShader_AddStaticParms(mode, permutation);
1053         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1054         vertstrings_count += shaderstaticparms_count;
1055         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056         geomstrings_count += shaderstaticparms_count;
1057         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058         fragstrings_count += shaderstaticparms_count;
1059
1060         // now append the shader text itself
1061         vertstrings_list[vertstrings_count++] = vertexstring;
1062         geomstrings_list[geomstrings_count++] = geometrystring;
1063         fragstrings_list[fragstrings_count++] = fragmentstring;
1064
1065         // if any sources were NULL, clear the respective list
1066         if (!vertexstring)
1067                 vertstrings_count = 0;
1068         if (!geometrystring)
1069                 geomstrings_count = 0;
1070         if (!fragmentstring)
1071                 fragstrings_count = 0;
1072
1073         // compile the shader program
1074         if (vertstrings_count + geomstrings_count + fragstrings_count)
1075                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1076         if (p->program)
1077         {
1078                 CHECKGLERROR
1079                 qglUseProgram(p->program);CHECKGLERROR
1080                 // look up all the uniform variable names we care about, so we don't
1081                 // have to look them up every time we set them
1082
1083                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1084                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1085                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1086                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1087                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1088                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1089                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1090                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1091                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1092                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1093                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1094                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1095                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1096                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1097                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1098                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1099                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1100                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1101                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1102                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1103                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1104                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1105                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1106                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1107                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1108                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1109                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1110                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1111                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1112                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1113                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1114                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1115                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1116                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1117                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1118                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1119                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1120                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1121                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1122                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1123                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1124                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1125                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1126                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1127                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1128                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1129                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1130                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1131                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1132                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1133                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1134                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1135                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1136                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1137                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1138                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1139                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1140                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1141                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1142                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1143                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1144                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1145                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1146                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1147                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1148                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1149                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1150                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1151                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1152                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1153                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1154                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1155                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1156                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1157                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1158                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1159                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1160                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1161                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1162                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1163                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1164                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1165                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1166                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1167                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1168                 // initialize the samplers to refer to the texture units we use
1169                 p->tex_Texture_First = -1;
1170                 p->tex_Texture_Second = -1;
1171                 p->tex_Texture_GammaRamps = -1;
1172                 p->tex_Texture_Normal = -1;
1173                 p->tex_Texture_Color = -1;
1174                 p->tex_Texture_Gloss = -1;
1175                 p->tex_Texture_Glow = -1;
1176                 p->tex_Texture_SecondaryNormal = -1;
1177                 p->tex_Texture_SecondaryColor = -1;
1178                 p->tex_Texture_SecondaryGloss = -1;
1179                 p->tex_Texture_SecondaryGlow = -1;
1180                 p->tex_Texture_Pants = -1;
1181                 p->tex_Texture_Shirt = -1;
1182                 p->tex_Texture_FogHeightTexture = -1;
1183                 p->tex_Texture_FogMask = -1;
1184                 p->tex_Texture_Lightmap = -1;
1185                 p->tex_Texture_Deluxemap = -1;
1186                 p->tex_Texture_Attenuation = -1;
1187                 p->tex_Texture_Cube = -1;
1188                 p->tex_Texture_Refraction = -1;
1189                 p->tex_Texture_Reflection = -1;
1190                 p->tex_Texture_ShadowMap2D = -1;
1191                 p->tex_Texture_CubeProjection = -1;
1192                 p->tex_Texture_ScreenDepth = -1;
1193                 p->tex_Texture_ScreenNormalMap = -1;
1194                 p->tex_Texture_ScreenDiffuse = -1;
1195                 p->tex_Texture_ScreenSpecular = -1;
1196                 p->tex_Texture_ReflectMask = -1;
1197                 p->tex_Texture_ReflectCube = -1;
1198                 p->tex_Texture_BounceGrid = -1;
1199                 sampler = 0;
1200                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1201                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1202                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1203                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1204                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1205                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1206                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1207                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1208                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1209                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1210                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1211                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1212                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1213                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1214                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1215                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1216                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1217                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1218                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1219                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1220                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1221                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1222                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1223                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1224                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1225                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1226                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1227                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1228                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1229                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1230                 CHECKGLERROR
1231                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1232         }
1233         else
1234                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1235
1236         // free the strings
1237         if (vertexstring)
1238                 Mem_Free(vertexstring);
1239         if (geometrystring)
1240                 Mem_Free(geometrystring);
1241         if (fragmentstring)
1242                 Mem_Free(fragmentstring);
1243 }
1244
1245 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1246 {
1247         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1248         if (r_glsl_permutation != perm)
1249         {
1250                 r_glsl_permutation = perm;
1251                 if (!r_glsl_permutation->program)
1252                 {
1253                         if (!r_glsl_permutation->compiled)
1254                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1255                         if (!r_glsl_permutation->program)
1256                         {
1257                                 // remove features until we find a valid permutation
1258                                 int i;
1259                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1260                                 {
1261                                         // reduce i more quickly whenever it would not remove any bits
1262                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1263                                         if (!(permutation & j))
1264                                                 continue;
1265                                         permutation -= j;
1266                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1267                                         if (!r_glsl_permutation->compiled)
1268                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1269                                         if (r_glsl_permutation->program)
1270                                                 break;
1271                                 }
1272                                 if (i >= SHADERPERMUTATION_COUNT)
1273                                 {
1274                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1275                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1276                                         qglUseProgram(0);CHECKGLERROR
1277                                         return; // no bit left to clear, entire mode is broken
1278                                 }
1279                         }
1280                 }
1281                 CHECKGLERROR
1282                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1283         }
1284         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1285         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1286         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1287 }
1288
1289 #ifdef SUPPORTD3D
1290
1291 #ifdef SUPPORTD3D
1292 #include <d3d9.h>
1293 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1294 extern D3DCAPS9 vid_d3d9caps;
1295 #endif
1296
1297 struct r_hlsl_permutation_s;
1298 typedef struct r_hlsl_permutation_s
1299 {
1300         /// hash lookup data
1301         struct r_hlsl_permutation_s *hashnext;
1302         unsigned int mode;
1303         unsigned int permutation;
1304
1305         /// indicates if we have tried compiling this permutation already
1306         qboolean compiled;
1307         /// NULL if compilation failed
1308         IDirect3DVertexShader9 *vertexshader;
1309         IDirect3DPixelShader9 *pixelshader;
1310 }
1311 r_hlsl_permutation_t;
1312
1313 typedef enum D3DVSREGISTER_e
1314 {
1315         D3DVSREGISTER_TexMatrix = 0, // float4x4
1316         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1317         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1318         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1319         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1320         D3DVSREGISTER_ModelToLight = 20, // float4x4
1321         D3DVSREGISTER_EyePosition = 24,
1322         D3DVSREGISTER_FogPlane = 25,
1323         D3DVSREGISTER_LightDir = 26,
1324         D3DVSREGISTER_LightPosition = 27,
1325 }
1326 D3DVSREGISTER_t;
1327
1328 typedef enum D3DPSREGISTER_e
1329 {
1330         D3DPSREGISTER_Alpha = 0,
1331         D3DPSREGISTER_BloomBlur_Parameters = 1,
1332         D3DPSREGISTER_ClientTime = 2,
1333         D3DPSREGISTER_Color_Ambient = 3,
1334         D3DPSREGISTER_Color_Diffuse = 4,
1335         D3DPSREGISTER_Color_Specular = 5,
1336         D3DPSREGISTER_Color_Glow = 6,
1337         D3DPSREGISTER_Color_Pants = 7,
1338         D3DPSREGISTER_Color_Shirt = 8,
1339         D3DPSREGISTER_DeferredColor_Ambient = 9,
1340         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1341         D3DPSREGISTER_DeferredColor_Specular = 11,
1342         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1343         D3DPSREGISTER_DeferredMod_Specular = 13,
1344         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1345         D3DPSREGISTER_EyePosition = 15, // unused
1346         D3DPSREGISTER_FogColor = 16,
1347         D3DPSREGISTER_FogHeightFade = 17,
1348         D3DPSREGISTER_FogPlane = 18,
1349         D3DPSREGISTER_FogPlaneViewDist = 19,
1350         D3DPSREGISTER_FogRangeRecip = 20,
1351         D3DPSREGISTER_LightColor = 21,
1352         D3DPSREGISTER_LightDir = 22, // unused
1353         D3DPSREGISTER_LightPosition = 23,
1354         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1355         D3DPSREGISTER_PixelSize = 25,
1356         D3DPSREGISTER_ReflectColor = 26,
1357         D3DPSREGISTER_ReflectFactor = 27,
1358         D3DPSREGISTER_ReflectOffset = 28,
1359         D3DPSREGISTER_RefractColor = 29,
1360         D3DPSREGISTER_Saturation = 30,
1361         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1362         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1363         D3DPSREGISTER_ScreenToDepth = 33,
1364         D3DPSREGISTER_ShadowMap_Parameters = 34,
1365         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1366         D3DPSREGISTER_SpecularPower = 36,
1367         D3DPSREGISTER_UserVec1 = 37,
1368         D3DPSREGISTER_UserVec2 = 38,
1369         D3DPSREGISTER_UserVec3 = 39,
1370         D3DPSREGISTER_UserVec4 = 40,
1371         D3DPSREGISTER_ViewTintColor = 41,
1372         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1373         D3DPSREGISTER_BloomColorSubtract = 43,
1374         D3DPSREGISTER_ViewToLight = 44, // float4x4
1375         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1376         D3DPSREGISTER_NormalmapScrollBlend = 52,
1377         // next at 53
1378 }
1379 D3DPSREGISTER_t;
1380
1381 /// information about each possible shader permutation
1382 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1383 /// currently selected permutation
1384 r_hlsl_permutation_t *r_hlsl_permutation;
1385 /// storage for permutations linked in the hash table
1386 memexpandablearray_t r_hlsl_permutationarray;
1387
1388 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1389 {
1390         //unsigned int hashdepth = 0;
1391         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1392         r_hlsl_permutation_t *p;
1393         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1394         {
1395                 if (p->mode == mode && p->permutation == permutation)
1396                 {
1397                         //if (hashdepth > 10)
1398                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1399                         return p;
1400                 }
1401                 //hashdepth++;
1402         }
1403         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1404         p->mode = mode;
1405         p->permutation = permutation;
1406         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1407         r_hlsl_permutationhash[mode][hashindex] = p;
1408         //if (hashdepth > 10)
1409         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1410         return p;
1411 }
1412
1413 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1414 {
1415         char *shaderstring;
1416         if (!filename || !filename[0])
1417                 return NULL;
1418         if (!strcmp(filename, "hlsl/default.hlsl"))
1419         {
1420                 if (!hlslshaderstring)
1421                 {
1422                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1423                         if (hlslshaderstring)
1424                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1425                         else
1426                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1427                 }
1428                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1429                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1430                 return shaderstring;
1431         }
1432         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1433         if (shaderstring)
1434         {
1435                 if (printfromdisknotice)
1436                         Con_DPrintf("from disk %s... ", filename);
1437                 return shaderstring;
1438         }
1439         return shaderstring;
1440 }
1441
1442 #include <d3dx9.h>
1443 //#include <d3dx9shader.h>
1444 //#include <d3dx9mesh.h>
1445
1446 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1447 {
1448         DWORD *vsbin = NULL;
1449         DWORD *psbin = NULL;
1450         fs_offset_t vsbinsize;
1451         fs_offset_t psbinsize;
1452 //      IDirect3DVertexShader9 *vs = NULL;
1453 //      IDirect3DPixelShader9 *ps = NULL;
1454         ID3DXBuffer *vslog = NULL;
1455         ID3DXBuffer *vsbuffer = NULL;
1456         ID3DXConstantTable *vsconstanttable = NULL;
1457         ID3DXBuffer *pslog = NULL;
1458         ID3DXBuffer *psbuffer = NULL;
1459         ID3DXConstantTable *psconstanttable = NULL;
1460         int vsresult = 0;
1461         int psresult = 0;
1462         char temp[MAX_INPUTLINE];
1463         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1464         qboolean debugshader = gl_paranoid.integer != 0;
1465         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1466         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1467         if (!debugshader)
1468         {
1469                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1470                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1471         }
1472         if ((!vsbin && vertstring) || (!psbin && fragstring))
1473         {
1474                 const char* dllnames_d3dx9 [] =
1475                 {
1476                         "d3dx9_43.dll",
1477                         "d3dx9_42.dll",
1478                         "d3dx9_41.dll",
1479                         "d3dx9_40.dll",
1480                         "d3dx9_39.dll",
1481                         "d3dx9_38.dll",
1482                         "d3dx9_37.dll",
1483                         "d3dx9_36.dll",
1484                         "d3dx9_35.dll",
1485                         "d3dx9_34.dll",
1486                         "d3dx9_33.dll",
1487                         "d3dx9_32.dll",
1488                         "d3dx9_31.dll",
1489                         "d3dx9_30.dll",
1490                         "d3dx9_29.dll",
1491                         "d3dx9_28.dll",
1492                         "d3dx9_27.dll",
1493                         "d3dx9_26.dll",
1494                         "d3dx9_25.dll",
1495                         "d3dx9_24.dll",
1496                         NULL
1497                 };
1498                 dllhandle_t d3dx9_dll = NULL;
1499                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1500                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1501                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502                 dllfunction_t d3dx9_dllfuncs[] =
1503                 {
1504                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1505                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1506                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1507                         {NULL, NULL}
1508                 };
1509                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1510                 {
1511                         DWORD shaderflags = 0;
1512                         if (debugshader)
1513                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1514                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1515                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1516                         if (vertstring && vertstring[0])
1517                         {
1518                                 if (debugshader)
1519                                 {
1520 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1521 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1522                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1523                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1524                                 }
1525                                 else
1526                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1527                                 if (vsbuffer)
1528                                 {
1529                                         vsbinsize = vsbuffer->GetBufferSize();
1530                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1531                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1532                                         vsbuffer->Release();
1533                                 }
1534                                 if (vslog)
1535                                 {
1536                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1537                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1538                                         vslog->Release();
1539                                 }
1540                         }
1541                         if (fragstring && fragstring[0])
1542                         {
1543                                 if (debugshader)
1544                                 {
1545 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1546 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1547                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1548                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1549                                 }
1550                                 else
1551                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1552                                 if (psbuffer)
1553                                 {
1554                                         psbinsize = psbuffer->GetBufferSize();
1555                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1556                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1557                                         psbuffer->Release();
1558                                 }
1559                                 if (pslog)
1560                                 {
1561                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1562                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1563                                         pslog->Release();
1564                                 }
1565                         }
1566                         Sys_UnloadLibrary(&d3dx9_dll);
1567                 }
1568                 else
1569                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1570         }
1571         if (vsbin && psbin)
1572         {
1573                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1574                 if (FAILED(vsresult))
1575                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1576                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1577                 if (FAILED(psresult))
1578                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1579         }
1580         // free the shader data
1581         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1582         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1583 }
1584
1585 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1586 {
1587         int i;
1588         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1589         int vertstring_length = 0;
1590         int geomstring_length = 0;
1591         int fragstring_length = 0;
1592         char *t;
1593         char *vertexstring, *geometrystring, *fragmentstring;
1594         char *vertstring, *geomstring, *fragstring;
1595         char permutationname[256];
1596         char cachename[256];
1597         int vertstrings_count = 0;
1598         int geomstrings_count = 0;
1599         int fragstrings_count = 0;
1600         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603
1604         if (p->compiled)
1605                 return;
1606         p->compiled = true;
1607         p->vertexshader = NULL;
1608         p->pixelshader = NULL;
1609
1610         permutationname[0] = 0;
1611         cachename[0] = 0;
1612         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1613         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1614         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1615
1616         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1617         strlcat(cachename, "hlsl/", sizeof(cachename));
1618
1619         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1620         vertstrings_count = 0;
1621         geomstrings_count = 0;
1622         fragstrings_count = 0;
1623         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1624         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1625         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1626
1627         // the first pretext is which type of shader to compile as
1628         // (later these will all be bound together as a program object)
1629         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1630         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1631         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1632
1633         // the second pretext is the mode (for example a light source)
1634         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1635         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1636         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1637         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1638         strlcat(cachename, modeinfo->name, sizeof(cachename));
1639
1640         // now add all the permutation pretexts
1641         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1642         {
1643                 if (permutation & (1<<i))
1644                 {
1645                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1646                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1647                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1648                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1649                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1650                 }
1651                 else
1652                 {
1653                         // keep line numbers correct
1654                         vertstrings_list[vertstrings_count++] = "\n";
1655                         geomstrings_list[geomstrings_count++] = "\n";
1656                         fragstrings_list[fragstrings_count++] = "\n";
1657                 }
1658         }
1659
1660         // add static parms
1661         R_CompileShader_AddStaticParms(mode, permutation);
1662         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1663         vertstrings_count += shaderstaticparms_count;
1664         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665         geomstrings_count += shaderstaticparms_count;
1666         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667         fragstrings_count += shaderstaticparms_count;
1668
1669         // replace spaces in the cachename with _ characters
1670         for (i = 0;cachename[i];i++)
1671                 if (cachename[i] == ' ')
1672                         cachename[i] = '_';
1673
1674         // now append the shader text itself
1675         vertstrings_list[vertstrings_count++] = vertexstring;
1676         geomstrings_list[geomstrings_count++] = geometrystring;
1677         fragstrings_list[fragstrings_count++] = fragmentstring;
1678
1679         // if any sources were NULL, clear the respective list
1680         if (!vertexstring)
1681                 vertstrings_count = 0;
1682         if (!geometrystring)
1683                 geomstrings_count = 0;
1684         if (!fragmentstring)
1685                 fragstrings_count = 0;
1686
1687         vertstring_length = 0;
1688         for (i = 0;i < vertstrings_count;i++)
1689                 vertstring_length += strlen(vertstrings_list[i]);
1690         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1691         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1692                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1693
1694         geomstring_length = 0;
1695         for (i = 0;i < geomstrings_count;i++)
1696                 geomstring_length += strlen(geomstrings_list[i]);
1697         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1698         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1699                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1700
1701         fragstring_length = 0;
1702         for (i = 0;i < fragstrings_count;i++)
1703                 fragstring_length += strlen(fragstrings_list[i]);
1704         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1705         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1706                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1707
1708         // try to load the cached shader, or generate one
1709         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1710
1711         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1712                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1713         else
1714                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1715
1716         // free the strings
1717         if (vertstring)
1718                 Mem_Free(vertstring);
1719         if (geomstring)
1720                 Mem_Free(geomstring);
1721         if (fragstring)
1722                 Mem_Free(fragstring);
1723         if (vertexstring)
1724                 Mem_Free(vertexstring);
1725         if (geometrystring)
1726                 Mem_Free(geometrystring);
1727         if (fragmentstring)
1728                 Mem_Free(fragmentstring);
1729 }
1730
1731 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1732 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1733 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1734 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1735 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1737
1738 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1741 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1742 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1743 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1744
1745 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1746 {
1747         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1748         if (r_hlsl_permutation != perm)
1749         {
1750                 r_hlsl_permutation = perm;
1751                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1752                 {
1753                         if (!r_hlsl_permutation->compiled)
1754                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1755                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1756                         {
1757                                 // remove features until we find a valid permutation
1758                                 int i;
1759                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1760                                 {
1761                                         // reduce i more quickly whenever it would not remove any bits
1762                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1763                                         if (!(permutation & j))
1764                                                 continue;
1765                                         permutation -= j;
1766                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1767                                         if (!r_hlsl_permutation->compiled)
1768                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1769                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1770                                                 break;
1771                                 }
1772                                 if (i >= SHADERPERMUTATION_COUNT)
1773                                 {
1774                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1775                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1776                                         return; // no bit left to clear, entire mode is broken
1777                                 }
1778                         }
1779                 }
1780                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1781                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1782         }
1783         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1784         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1785         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1786 }
1787 #endif
1788
1789 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1790 {
1791         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1792         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1793         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1794         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1795 }
1796
1797 void R_GLSL_Restart_f(void)
1798 {
1799         unsigned int i, limit;
1800         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1801                 Mem_Free(glslshaderstring);
1802         glslshaderstring = NULL;
1803         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1804                 Mem_Free(hlslshaderstring);
1805         hlslshaderstring = NULL;
1806         switch(vid.renderpath)
1807         {
1808         case RENDERPATH_D3D9:
1809 #ifdef SUPPORTD3D
1810                 {
1811                         r_hlsl_permutation_t *p;
1812                         r_hlsl_permutation = NULL;
1813                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1814                         for (i = 0;i < limit;i++)
1815                         {
1816                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1817                                 {
1818                                         if (p->vertexshader)
1819                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1820                                         if (p->pixelshader)
1821                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1822                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1823                                 }
1824                         }
1825                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1826                 }
1827 #endif
1828                 break;
1829         case RENDERPATH_D3D10:
1830                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1831                 break;
1832         case RENDERPATH_D3D11:
1833                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1834                 break;
1835         case RENDERPATH_GL20:
1836         case RENDERPATH_GLES2:
1837                 {
1838                         r_glsl_permutation_t *p;
1839                         r_glsl_permutation = NULL;
1840                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1841                         for (i = 0;i < limit;i++)
1842                         {
1843                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1844                                 {
1845                                         GL_Backend_FreeProgram(p->program);
1846                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1847                                 }
1848                         }
1849                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1850                 }
1851                 break;
1852         case RENDERPATH_GL13:
1853         case RENDERPATH_GL11:
1854                 break;
1855         case RENDERPATH_SOFT:
1856                 break;
1857         }
1858 }
1859
1860 void R_GLSL_DumpShader_f(void)
1861 {
1862         int i;
1863         qfile_t *file;
1864
1865         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1866         if (file)
1867         {
1868                 FS_Print(file, "/* The engine may define the following macros:\n");
1869                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1870                 for (i = 0;i < SHADERMODE_COUNT;i++)
1871                         FS_Print(file, glslshadermodeinfo[i].pretext);
1872                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1873                         FS_Print(file, shaderpermutationinfo[i].pretext);
1874                 FS_Print(file, "*/\n");
1875                 FS_Print(file, builtinshaderstring);
1876                 FS_Close(file);
1877                 Con_Printf("glsl/default.glsl written\n");
1878         }
1879         else
1880                 Con_Printf("failed to write to glsl/default.glsl\n");
1881
1882         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1883         if (file)
1884         {
1885                 FS_Print(file, "/* The engine may define the following macros:\n");
1886                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1887                 for (i = 0;i < SHADERMODE_COUNT;i++)
1888                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1889                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1890                         FS_Print(file, shaderpermutationinfo[i].pretext);
1891                 FS_Print(file, "*/\n");
1892                 FS_Print(file, builtinhlslshaderstring);
1893                 FS_Close(file);
1894                 Con_Printf("hlsl/default.hlsl written\n");
1895         }
1896         else
1897                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1898 }
1899
1900 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1901 {
1902         if (!second)
1903                 texturemode = GL_MODULATE;
1904         switch (vid.renderpath)
1905         {
1906         case RENDERPATH_D3D9:
1907 #ifdef SUPPORTD3D
1908                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1909                 R_Mesh_TexBind(GL20TU_FIRST , first );
1910                 R_Mesh_TexBind(GL20TU_SECOND, second);
1911 #endif
1912                 break;
1913         case RENDERPATH_D3D10:
1914                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1915                 break;
1916         case RENDERPATH_D3D11:
1917                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1918                 break;
1919         case RENDERPATH_GL20:
1920         case RENDERPATH_GLES2:
1921                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1922                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1923                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1924                 break;
1925         case RENDERPATH_GL13:
1926                 R_Mesh_TexBind(0, first );
1927                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1928                 R_Mesh_TexBind(1, second);
1929                 if (second)
1930                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1931                 break;
1932         case RENDERPATH_GL11:
1933                 R_Mesh_TexBind(0, first );
1934                 break;
1935         case RENDERPATH_SOFT:
1936                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1937                 R_Mesh_TexBind(GL20TU_FIRST , first );
1938                 R_Mesh_TexBind(GL20TU_SECOND, second);
1939                 break;
1940         }
1941 }
1942
1943 void R_SetupShader_DepthOrShadow(void)
1944 {
1945         switch (vid.renderpath)
1946         {
1947         case RENDERPATH_D3D9:
1948 #ifdef SUPPORTD3D
1949                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1950 #endif
1951                 break;
1952         case RENDERPATH_D3D10:
1953                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1954                 break;
1955         case RENDERPATH_D3D11:
1956                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1957                 break;
1958         case RENDERPATH_GL20:
1959         case RENDERPATH_GLES2:
1960                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1961                 break;
1962         case RENDERPATH_GL13:
1963                 R_Mesh_TexBind(0, 0);
1964                 R_Mesh_TexBind(1, 0);
1965                 break;
1966         case RENDERPATH_GL11:
1967                 R_Mesh_TexBind(0, 0);
1968                 break;
1969         case RENDERPATH_SOFT:
1970                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1971                 break;
1972         }
1973 }
1974
1975 void R_SetupShader_ShowDepth(void)
1976 {
1977         switch (vid.renderpath)
1978         {
1979         case RENDERPATH_D3D9:
1980 #ifdef SUPPORTHLSL
1981                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1982 #endif
1983                 break;
1984         case RENDERPATH_D3D10:
1985                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1986                 break;
1987         case RENDERPATH_D3D11:
1988                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1989                 break;
1990         case RENDERPATH_GL20:
1991         case RENDERPATH_GLES2:
1992                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1993                 break;
1994         case RENDERPATH_GL13:
1995                 break;
1996         case RENDERPATH_GL11:
1997                 break;
1998         case RENDERPATH_SOFT:
1999                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2000                 break;
2001         }
2002 }
2003
2004 extern qboolean r_shadow_usingdeferredprepass;
2005 extern cvar_t r_shadow_deferred_8bitrange;
2006 extern rtexture_t *r_shadow_attenuationgradienttexture;
2007 extern rtexture_t *r_shadow_attenuation2dtexture;
2008 extern rtexture_t *r_shadow_attenuation3dtexture;
2009 extern qboolean r_shadow_usingshadowmap2d;
2010 extern qboolean r_shadow_usingshadowmaportho;
2011 extern float r_shadow_shadowmap_texturescale[2];
2012 extern float r_shadow_shadowmap_parameters[4];
2013 extern qboolean r_shadow_shadowmapvsdct;
2014 extern qboolean r_shadow_shadowmapsampler;
2015 extern int r_shadow_shadowmappcf;
2016 extern rtexture_t *r_shadow_shadowmap2dtexture;
2017 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2018 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2019 extern matrix4x4_t r_shadow_shadowmapmatrix;
2020 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2021 extern int r_shadow_prepass_width;
2022 extern int r_shadow_prepass_height;
2023 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2024 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2025 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2026 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2027 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2028
2029 #define BLENDFUNC_ALLOWS_COLORMOD      1
2030 #define BLENDFUNC_ALLOWS_FOG           2
2031 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2032 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2033 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2034 static int R_BlendFuncFlags(int src, int dst)
2035 {
2036         int r = 0;
2037
2038         // a blendfunc allows colormod if:
2039         // a) it can never keep the destination pixel invariant, or
2040         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2041         // this is to prevent unintended side effects from colormod
2042
2043         // a blendfunc allows fog if:
2044         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2045         // this is to prevent unintended side effects from fog
2046
2047         // these checks are the output of fogeval.pl
2048
2049         r |= BLENDFUNC_ALLOWS_COLORMOD;
2050         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2051         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2052         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2053         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2054         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2055         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2056         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2057         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2058         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2059         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2060         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2061         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2063         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2064         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2065         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2066         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2067         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2068         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2069         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2070         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2071
2072         return r;
2073 }
2074
2075 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
2076 {
2077         // select a permutation of the lighting shader appropriate to this
2078         // combination of texture, entity, light source, and fogging, only use the
2079         // minimum features necessary to avoid wasting rendering time in the
2080         // fragment shader on features that are not being used
2081         unsigned int permutation = 0;
2082         unsigned int mode = 0;
2083         int blendfuncflags;
2084         static float dummy_colormod[3] = {1, 1, 1};
2085         float *colormod = rsurface.colormod;
2086         float m16f[16];
2087         matrix4x4_t tempmatrix;
2088         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2089         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2090                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2091         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2092                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2093         if (rsurfacepass == RSURFPASS_BACKGROUND)
2094         {
2095                 // distorted background
2096                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2097                 {
2098                         mode = SHADERMODE_WATER;
2099                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2100                         {
2101                                 // this is the right thing to do for wateralpha
2102                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2103                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2104                         }
2105                         else
2106                         {
2107                                 // this is the right thing to do for entity alpha
2108                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2109                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2110                         }
2111                 }
2112                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2113                 {
2114                         mode = SHADERMODE_REFRACTION;
2115                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2116                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2117                 }
2118                 else
2119                 {
2120                         mode = SHADERMODE_GENERIC;
2121                         permutation |= SHADERPERMUTATION_DIFFUSE;
2122                         GL_BlendFunc(GL_ONE, GL_ZERO);
2123                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2124                 }
2125         }
2126         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2127         {
2128                 if (r_glsl_offsetmapping.integer)
2129                 {
2130                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2131                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2132                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2133                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2134                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2135                         {
2136                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2137                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2138                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2139                         }
2140                 }
2141                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2142                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2143                 // normalmap (deferred prepass), may use alpha test on diffuse
2144                 mode = SHADERMODE_DEFERREDGEOMETRY;
2145                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2146                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2147                 GL_BlendFunc(GL_ONE, GL_ZERO);
2148                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2149         }
2150         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2151         {
2152                 if (r_glsl_offsetmapping.integer)
2153                 {
2154                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2155                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2156                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2157                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2158                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2159                         {
2160                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2161                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2162                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2163                         }
2164                 }
2165                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2166                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2167                 // light source
2168                 mode = SHADERMODE_LIGHTSOURCE;
2169                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2170                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2171                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2172                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2173                 if (diffusescale > 0)
2174                         permutation |= SHADERPERMUTATION_DIFFUSE;
2175                 if (specularscale > 0)
2176                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2177                 if (r_refdef.fogenabled)
2178                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2179                 if (rsurface.texture->colormapping)
2180                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2181                 if (r_shadow_usingshadowmap2d)
2182                 {
2183                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2184                         if(r_shadow_shadowmapvsdct)
2185                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2186
2187                         if (r_shadow_shadowmapsampler)
2188                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2189                         if (r_shadow_shadowmappcf > 1)
2190                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2191                         else if (r_shadow_shadowmappcf)
2192                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2193                 }
2194                 if (rsurface.texture->reflectmasktexture)
2195                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2196                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2197                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2198         }
2199         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2200         {
2201                 if (r_glsl_offsetmapping.integer)
2202                 {
2203                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2204                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2205                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2206                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2207                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2208                         {
2209                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2210                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2211                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2212                         }
2213                 }
2214                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2215                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2216                 // unshaded geometry (fullbright or ambient model lighting)
2217                 mode = SHADERMODE_FLATCOLOR;
2218                 ambientscale = diffusescale = specularscale = 0;
2219                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2220                         permutation |= SHADERPERMUTATION_GLOW;
2221                 if (r_refdef.fogenabled)
2222                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2223                 if (rsurface.texture->colormapping)
2224                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2225                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2226                 {
2227                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2228                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2229
2230                         if (r_shadow_shadowmapsampler)
2231                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2232                         if (r_shadow_shadowmappcf > 1)
2233                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2234                         else if (r_shadow_shadowmappcf)
2235                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2236                 }
2237                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2238                         permutation |= SHADERPERMUTATION_REFLECTION;
2239                 if (rsurface.texture->reflectmasktexture)
2240                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2241                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2242                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2243         }
2244         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2245         {
2246                 if (r_glsl_offsetmapping.integer)
2247                 {
2248                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2249                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2250                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2251                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2252                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2253                         {
2254                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2255                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2256                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2257                         }
2258                 }
2259                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2260                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2261                 // directional model lighting
2262                 mode = SHADERMODE_LIGHTDIRECTION;
2263                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2264                         permutation |= SHADERPERMUTATION_GLOW;
2265                 permutation |= SHADERPERMUTATION_DIFFUSE;
2266                 if (specularscale > 0)
2267                         permutation |= SHADERPERMUTATION_SPECULAR;
2268                 if (r_refdef.fogenabled)
2269                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2270                 if (rsurface.texture->colormapping)
2271                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2272                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2273                 {
2274                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2275                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2276
2277                         if (r_shadow_shadowmapsampler)
2278                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2279                         if (r_shadow_shadowmappcf > 1)
2280                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2281                         else if (r_shadow_shadowmappcf)
2282                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2283                 }
2284                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2285                         permutation |= SHADERPERMUTATION_REFLECTION;
2286                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2287                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2288                 if (rsurface.texture->reflectmasktexture)
2289                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2290                 if (r_shadow_bouncegridtexture)
2291                 {
2292                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2293                         if (r_shadow_bouncegriddirectional)
2294                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2295                 }
2296                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2297                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2298         }
2299         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2300         {
2301                 if (r_glsl_offsetmapping.integer)
2302                 {
2303                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2304                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2305                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2306                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2307                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2308                         {
2309                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2310                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2311                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2312                         }
2313                 }
2314                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2315                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2316                 // ambient model lighting
2317                 mode = SHADERMODE_LIGHTDIRECTION;
2318                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2319                         permutation |= SHADERPERMUTATION_GLOW;
2320                 if (r_refdef.fogenabled)
2321                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2322                 if (rsurface.texture->colormapping)
2323                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2324                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2325                 {
2326                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2327                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2328
2329                         if (r_shadow_shadowmapsampler)
2330                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2331                         if (r_shadow_shadowmappcf > 1)
2332                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2333                         else if (r_shadow_shadowmappcf)
2334                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2335                 }
2336                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2337                         permutation |= SHADERPERMUTATION_REFLECTION;
2338                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2339                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2340                 if (rsurface.texture->reflectmasktexture)
2341                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2342                 if (r_shadow_bouncegridtexture)
2343                 {
2344                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2345                         if (r_shadow_bouncegriddirectional)
2346                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2347                 }
2348                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2349                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2350         }
2351         else
2352         {
2353                 if (r_glsl_offsetmapping.integer)
2354                 {
2355                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2356                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2357                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2358                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2359                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2360                         {
2361                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2362                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2363                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2364                         }
2365                 }
2366                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2367                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2368                 // lightmapped wall
2369                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2370                         permutation |= SHADERPERMUTATION_GLOW;
2371                 if (r_refdef.fogenabled)
2372                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2373                 if (rsurface.texture->colormapping)
2374                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2375                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2376                 {
2377                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2378                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2379
2380                         if (r_shadow_shadowmapsampler)
2381                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2382                         if (r_shadow_shadowmappcf > 1)
2383                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2384                         else if (r_shadow_shadowmappcf)
2385                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2386                 }
2387                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2388                         permutation |= SHADERPERMUTATION_REFLECTION;
2389                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2390                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2391                 if (rsurface.texture->reflectmasktexture)
2392                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2393                 if (FAKELIGHT_ENABLED)
2394                 {
2395                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2396                         mode = SHADERMODE_FAKELIGHT;
2397                         permutation |= SHADERPERMUTATION_DIFFUSE;
2398                         if (specularscale > 0)
2399                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2400                 }
2401                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2402                 {
2403                         // deluxemapping (light direction texture)
2404                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2405                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2406                         else
2407                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2408                         permutation |= SHADERPERMUTATION_DIFFUSE;
2409                         if (specularscale > 0)
2410                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2411                 }
2412                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2413                 {
2414                         // fake deluxemapping (uniform light direction in tangentspace)
2415                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2416                         permutation |= SHADERPERMUTATION_DIFFUSE;
2417                         if (specularscale > 0)
2418                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2419                 }
2420                 else if (rsurface.uselightmaptexture)
2421                 {
2422                         // ordinary lightmapping (q1bsp, q3bsp)
2423                         mode = SHADERMODE_LIGHTMAP;
2424                 }
2425                 else
2426                 {
2427                         // ordinary vertex coloring (q3bsp)
2428                         mode = SHADERMODE_VERTEXCOLOR;
2429                 }
2430                 if (r_shadow_bouncegridtexture)
2431                 {
2432                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2433                         if (r_shadow_bouncegriddirectional)
2434                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2435                 }
2436                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2437                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2438         }
2439         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2440                 colormod = dummy_colormod;
2441         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2442                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2443         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2444                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2445         switch(vid.renderpath)
2446         {
2447         case RENDERPATH_D3D9:
2448 #ifdef SUPPORTD3D
2449                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2450                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2451                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2452                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2453                 if (mode == SHADERMODE_LIGHTSOURCE)
2454                 {
2455                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2456                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2457                 }
2458                 else
2459                 {
2460                         if (mode == SHADERMODE_LIGHTDIRECTION)
2461                         {
2462                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2463                         }
2464                 }
2465                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2466                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2467                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2468                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2469                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2470
2471                 if (mode == SHADERMODE_LIGHTSOURCE)
2472                 {
2473                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2474                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2475                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2476                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2477                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2478
2479                         // additive passes are only darkened by fog, not tinted
2480                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2481                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2482                 }
2483                 else
2484                 {
2485                         if (mode == SHADERMODE_FLATCOLOR)
2486                         {
2487                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2488                         }
2489                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2490                         {
2491                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2492                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2493                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2494                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2495                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2496                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2497                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2498                         }
2499                         else
2500                         {
2501                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2502                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2503                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2504                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2505                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2506                         }
2507                         // additive passes are only darkened by fog, not tinted
2508                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2509                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2510                         else
2511                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2512                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2513                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2514                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2515                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2516                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2517                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2518                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2519                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2520                         if (mode == SHADERMODE_WATER)
2521                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2522                 }
2523                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2524                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2525                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2526                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2527                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2528                 if (rsurface.texture->pantstexture)
2529                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2530                 else
2531                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2532                 if (rsurface.texture->shirttexture)
2533                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2534                 else
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2536                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2537                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2538                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2539                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2540                 hlslPSSetParameter3f(D3DPSREGISTER_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2541                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2542                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2543
2544                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2545                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2546                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2547                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2548                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2549                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2550                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2551                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2552                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2553                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2554                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2555                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2556                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2557                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2558                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2559                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2560                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2561                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2562                 {
2563                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2564                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2565                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2566                 }
2567                 else
2568                 {
2569                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2570                 }
2571 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2572 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2573                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2574                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2575                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2576                 {
2577                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2578                         if (rsurface.rtlight)
2579                         {
2580                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2581                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2582                         }
2583                 }
2584 #endif
2585                 break;
2586         case RENDERPATH_D3D10:
2587                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2588                 break;
2589         case RENDERPATH_D3D11:
2590                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2591                 break;
2592         case RENDERPATH_GL20:
2593         case RENDERPATH_GLES2:
2594                 if (!vid.useinterleavedarrays)
2595                 {
2596                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2597                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2598                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2599                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2600                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2601                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2602                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2603                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2604                 }
2605                 else
2606                 {
2607                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2608                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2609                 }
2610                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2611                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2612                 if (mode == SHADERMODE_LIGHTSOURCE)
2613                 {
2614                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2615                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2616                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2617                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2618                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2619                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2620         
2621                         // additive passes are only darkened by fog, not tinted
2622                         if (r_glsl_permutation->loc_FogColor >= 0)
2623                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2624                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2625                 }
2626                 else
2627                 {
2628                         if (mode == SHADERMODE_FLATCOLOR)
2629                         {
2630                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2631                         }
2632                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2633                         {
2634                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2635                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2636                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2637                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2638                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2639                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2640                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2641                         }
2642                         else
2643                         {
2644                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2645                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2646                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2647                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2648                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2649                         }
2650                         // additive passes are only darkened by fog, not tinted
2651                         if (r_glsl_permutation->loc_FogColor >= 0)
2652                         {
2653                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2654                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2655                                 else
2656                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2657                         }
2658                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2659                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2660                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2661                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2662                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2663                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2664                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2665                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2666                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2667                 }
2668                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2669                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2670                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2671                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2672                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2673
2674                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2675                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2676                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2677                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2678                 {
2679                         if (rsurface.texture->pantstexture)
2680                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2681                         else
2682                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2683                 }
2684                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2685                 {
2686                         if (rsurface.texture->shirttexture)
2687                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2688                         else
2689                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2690                 }
2691                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2692                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2693                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2694                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2695                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform3f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2696                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2697                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2698                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2699                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2700
2701                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2702                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2703                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2704                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2705                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2706                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2707                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2708                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2709                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2710                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2711                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2712                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2713                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2714                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2715                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2716                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2717                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2718                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2719                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2720                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2721                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2722                 {
2723                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2724                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2725                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2726                 }
2727                 else
2728                 {
2729                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2730                 }
2731                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2732                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2733                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2734                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2735                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2736                 {
2737                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2738                         if (rsurface.rtlight)
2739                         {
2740                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2741                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2742                         }
2743                 }
2744                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2745                 CHECKGLERROR
2746                 break;
2747         case RENDERPATH_GL13:
2748         case RENDERPATH_GL11:
2749                 break;
2750         case RENDERPATH_SOFT:
2751                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2752                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2753                 R_SetupShader_SetPermutationSoft(mode, permutation);
2754                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2755                 if (mode == SHADERMODE_LIGHTSOURCE)
2756                 {
2757                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2758                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2759                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2760                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2761                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2762                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2763         
2764                         // additive passes are only darkened by fog, not tinted
2765                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2766                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2767                 }
2768                 else
2769                 {
2770                         if (mode == SHADERMODE_FLATCOLOR)
2771                         {
2772                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2773                         }
2774                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2775                         {
2776                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2777                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2778                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2779                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2782                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2783                         }
2784                         else
2785                         {
2786                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2787                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2788                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2789                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2790                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2791                         }
2792                         // additive passes are only darkened by fog, not tinted
2793                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2794                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2795                         else
2796                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2797                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2798                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2799                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2800                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2801                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2802                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2803                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2804                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2805                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2806                 }
2807                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2808                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2809                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2810                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2811                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2812
2813                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2814                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2815                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2816                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2817                 {
2818                         if (rsurface.texture->pantstexture)
2819                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2820                         else
2821                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2822                 }
2823                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2824                 {
2825                         if (rsurface.texture->shirttexture)
2826                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2827                         else
2828                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2829                 }
2830                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2831                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2832                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2833                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2834                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2835                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2836                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2837
2838                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2839                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2840                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2841                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2842                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2843                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2844                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2845                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2846                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2847                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2848                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2849                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2850                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2851                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2852                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2853                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2854                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2855                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2856                 {
2857                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2858                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2859                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2860                 }
2861                 else
2862                 {
2863                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2864                 }
2865 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2866 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2867                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2868                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2869                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2870                 {
2871                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2872                         if (rsurface.rtlight)
2873                         {
2874                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2875                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2876                         }
2877                 }
2878                 break;
2879         }
2880 }
2881
2882 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2883 {
2884         // select a permutation of the lighting shader appropriate to this
2885         // combination of texture, entity, light source, and fogging, only use the
2886         // minimum features necessary to avoid wasting rendering time in the
2887         // fragment shader on features that are not being used
2888         unsigned int permutation = 0;
2889         unsigned int mode = 0;
2890         const float *lightcolorbase = rtlight->currentcolor;
2891         float ambientscale = rtlight->ambientscale;
2892         float diffusescale = rtlight->diffusescale;
2893         float specularscale = rtlight->specularscale;
2894         // this is the location of the light in view space
2895         vec3_t viewlightorigin;
2896         // this transforms from view space (camera) to light space (cubemap)
2897         matrix4x4_t viewtolight;
2898         matrix4x4_t lighttoview;
2899         float viewtolight16f[16];
2900         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2901         // light source
2902         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2903         if (rtlight->currentcubemap != r_texture_whitecube)
2904                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2905         if (diffusescale > 0)
2906                 permutation |= SHADERPERMUTATION_DIFFUSE;
2907         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2908                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2909         if (r_shadow_usingshadowmap2d)
2910         {
2911                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2912                 if (r_shadow_shadowmapvsdct)
2913                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2914
2915                 if (r_shadow_shadowmapsampler)
2916                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2917                 if (r_shadow_shadowmappcf > 1)
2918                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2919                 else if (r_shadow_shadowmappcf)
2920                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2921         }
2922         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2923         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2924         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2925         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2926         switch(vid.renderpath)
2927         {
2928         case RENDERPATH_D3D9:
2929 #ifdef SUPPORTD3D
2930                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2931                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2932                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2933                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2934                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2935                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2936                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2937                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2938                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2939                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2940                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2941
2942                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2943                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2944                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2945                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2946                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2947                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2948 #endif
2949                 break;
2950         case RENDERPATH_D3D10:
2951                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2952                 break;
2953         case RENDERPATH_D3D11:
2954                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2955                 break;
2956         case RENDERPATH_GL20:
2957         case RENDERPATH_GLES2:
2958                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2959                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2960                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2961                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2962                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2963                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2964                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2965                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2966                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2967                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2968                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2969
2970                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2971                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2972                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2973                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2974                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2975                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2976                 break;
2977         case RENDERPATH_GL13:
2978         case RENDERPATH_GL11:
2979                 break;
2980         case RENDERPATH_SOFT:
2981                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2982                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2983                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2984                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2985                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2986                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2987                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2988                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2989                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2990                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2991                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2992
2993                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2994                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2995                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2996                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2997                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2998                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2999                 break;
3000         }
3001 }
3002
3003 #define SKINFRAME_HASH 1024
3004
3005 typedef struct
3006 {
3007         int loadsequence; // incremented each level change
3008         memexpandablearray_t array;
3009         skinframe_t *hash[SKINFRAME_HASH];
3010 }
3011 r_skinframe_t;
3012 r_skinframe_t r_skinframe;
3013
3014 void R_SkinFrame_PrepareForPurge(void)
3015 {
3016         r_skinframe.loadsequence++;
3017         // wrap it without hitting zero
3018         if (r_skinframe.loadsequence >= 200)
3019                 r_skinframe.loadsequence = 1;
3020 }
3021
3022 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3023 {
3024         if (!skinframe)
3025                 return;
3026         // mark the skinframe as used for the purging code
3027         skinframe->loadsequence = r_skinframe.loadsequence;
3028 }
3029
3030 void R_SkinFrame_Purge(void)
3031 {
3032         int i;
3033         skinframe_t *s;
3034         for (i = 0;i < SKINFRAME_HASH;i++)
3035         {
3036                 for (s = r_skinframe.hash[i];s;s = s->next)
3037                 {
3038                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3039                         {
3040                                 if (s->merged == s->base)
3041                                         s->merged = NULL;
3042                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3043                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3044                                 R_PurgeTexture(s->merged);s->merged = NULL;
3045                                 R_PurgeTexture(s->base  );s->base   = NULL;
3046                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3047                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3048                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3049                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3050                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3051                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3052                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3053                                 s->loadsequence = 0;
3054                         }
3055                 }
3056         }
3057 }
3058
3059 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3060         skinframe_t *item;
3061         char basename[MAX_QPATH];
3062
3063         Image_StripImageExtension(name, basename, sizeof(basename));
3064
3065         if( last == NULL ) {
3066                 int hashindex;
3067                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3068                 item = r_skinframe.hash[hashindex];
3069         } else {
3070                 item = last->next;
3071         }
3072
3073         // linearly search through the hash bucket
3074         for( ; item ; item = item->next ) {
3075                 if( !strcmp( item->basename, basename ) ) {
3076                         return item;
3077                 }
3078         }
3079         return NULL;
3080 }
3081
3082 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3083 {
3084         skinframe_t *item;
3085         int hashindex;
3086         char basename[MAX_QPATH];
3087
3088         Image_StripImageExtension(name, basename, sizeof(basename));
3089
3090         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3091         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3092                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3093                         break;
3094
3095         if (!item) {
3096                 rtexture_t *dyntexture;
3097                 // check whether its a dynamic texture
3098                 dyntexture = CL_GetDynTexture( basename );
3099                 if (!add && !dyntexture)
3100                         return NULL;
3101                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3102                 memset(item, 0, sizeof(*item));
3103                 strlcpy(item->basename, basename, sizeof(item->basename));
3104                 item->base = dyntexture; // either NULL or dyntexture handle
3105                 item->textureflags = textureflags;
3106                 item->comparewidth = comparewidth;
3107                 item->compareheight = compareheight;
3108                 item->comparecrc = comparecrc;
3109                 item->next = r_skinframe.hash[hashindex];
3110                 r_skinframe.hash[hashindex] = item;
3111         }
3112         else if( item->base == NULL )
3113         {
3114                 rtexture_t *dyntexture;
3115                 // check whether its a dynamic texture
3116                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3117                 dyntexture = CL_GetDynTexture( basename );
3118                 item->base = dyntexture; // either NULL or dyntexture handle
3119         }
3120
3121         R_SkinFrame_MarkUsed(item);
3122         return item;
3123 }
3124
3125 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3126         { \
3127                 unsigned long long avgcolor[5], wsum; \
3128                 int pix, comp, w; \
3129                 avgcolor[0] = 0; \
3130                 avgcolor[1] = 0; \
3131                 avgcolor[2] = 0; \
3132                 avgcolor[3] = 0; \
3133                 avgcolor[4] = 0; \
3134                 wsum = 0; \
3135                 for(pix = 0; pix < cnt; ++pix) \
3136                 { \
3137                         w = 0; \
3138                         for(comp = 0; comp < 3; ++comp) \
3139                                 w += getpixel; \
3140                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3141                         { \
3142                                 ++wsum; \
3143                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3144                                 w = getpixel; \
3145                                 for(comp = 0; comp < 3; ++comp) \
3146                                         avgcolor[comp] += getpixel * w; \
3147                                 avgcolor[3] += w; \
3148                         } \
3149                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3150                         avgcolor[4] += getpixel; \
3151                 } \
3152                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3153                         avgcolor[3] = 1; \
3154                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3155                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3156                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3157                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3158         }
3159
3160 extern cvar_t gl_picmip;
3161 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3162 {
3163         int j;
3164         unsigned char *pixels;
3165         unsigned char *bumppixels;
3166         unsigned char *basepixels = NULL;
3167         int basepixels_width = 0;
3168         int basepixels_height = 0;
3169         skinframe_t *skinframe;
3170         rtexture_t *ddsbase = NULL;
3171         qboolean ddshasalpha = false;
3172         float ddsavgcolor[4];
3173         char basename[MAX_QPATH];
3174         int miplevel = R_PicmipForFlags(textureflags);
3175         int savemiplevel = miplevel;
3176         int mymiplevel;
3177
3178         if (cls.state == ca_dedicated)
3179                 return NULL;
3180
3181         // return an existing skinframe if already loaded
3182         // if loading of the first image fails, don't make a new skinframe as it
3183         // would cause all future lookups of this to be missing
3184         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3185         if (skinframe && skinframe->base)
3186                 return skinframe;
3187
3188         Image_StripImageExtension(name, basename, sizeof(basename));
3189
3190         // check for DDS texture file first
3191         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3192         {
3193                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3194                 if (basepixels == NULL)
3195                         return NULL;
3196         }
3197
3198         // FIXME handle miplevel
3199
3200         if (developer_loading.integer)
3201                 Con_Printf("loading skin \"%s\"\n", name);
3202
3203         // we've got some pixels to store, so really allocate this new texture now
3204         if (!skinframe)
3205                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3206         skinframe->stain = NULL;
3207         skinframe->merged = NULL;
3208         skinframe->base = NULL;
3209         skinframe->pants = NULL;
3210         skinframe->shirt = NULL;
3211         skinframe->nmap = NULL;
3212         skinframe->gloss = NULL;
3213         skinframe->glow = NULL;
3214         skinframe->fog = NULL;
3215         skinframe->reflect = NULL;
3216         skinframe->hasalpha = false;
3217
3218         if (ddsbase)
3219         {
3220                 skinframe->base = ddsbase;
3221                 skinframe->hasalpha = ddshasalpha;
3222                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3223                 if (r_loadfog && skinframe->hasalpha)
3224                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3225                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3226         }
3227         else
3228         {
3229                 basepixels_width = image_width;
3230                 basepixels_height = image_height;
3231                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3232                 if (textureflags & TEXF_ALPHA)
3233                 {
3234                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3235                         {
3236                                 if (basepixels[j] < 255)
3237                                 {
3238                                         skinframe->hasalpha = true;
3239                                         break;
3240                                 }
3241                         }
3242                         if (r_loadfog && skinframe->hasalpha)
3243                         {
3244                                 // has transparent pixels
3245                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3246                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3247                                 {
3248                                         pixels[j+0] = 255;
3249                                         pixels[j+1] = 255;
3250                                         pixels[j+2] = 255;
3251                                         pixels[j+3] = basepixels[j+3];
3252                                 }
3253                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3254                                 Mem_Free(pixels);
3255                         }
3256                 }
3257                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3258                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3259                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3260                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3261                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3262                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3263         }
3264
3265         if (r_loaddds)
3266         {
3267                 mymiplevel = savemiplevel;
3268                 if (r_loadnormalmap)
3269                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3270                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3271                 if (r_loadgloss)
3272                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3273                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3275                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3276         }
3277
3278         // _norm is the name used by tenebrae and has been adopted as standard
3279         if (r_loadnormalmap && skinframe->nmap == NULL)
3280         {
3281                 mymiplevel = savemiplevel;
3282                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3283                 {
3284                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3285                         Mem_Free(pixels);
3286                         pixels = NULL;
3287                 }
3288                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3289                 {
3290                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3291                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3292                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3293                         Mem_Free(pixels);
3294                         Mem_Free(bumppixels);
3295                 }
3296                 else if (r_shadow_bumpscale_basetexture.value > 0)
3297                 {
3298                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3299                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3300                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3301                         Mem_Free(pixels);
3302                 }
3303                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3304                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3305         }
3306
3307         // _luma is supported only for tenebrae compatibility
3308         // _glow is the preferred name
3309         mymiplevel = savemiplevel;
3310         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
3311         {
3312                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3313                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3314                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3315                 Mem_Free(pixels);pixels = NULL;
3316         }
3317
3318         mymiplevel = savemiplevel;
3319         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3320         {
3321                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3322                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3323                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3324                 Mem_Free(pixels);
3325                 pixels = NULL;
3326         }
3327
3328         mymiplevel = savemiplevel;
3329         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3330         {
3331                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3332                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3333                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3334                 Mem_Free(pixels);
3335                 pixels = NULL;
3336         }
3337
3338         mymiplevel = savemiplevel;
3339         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3340         {
3341                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3342                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3343                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3344                 Mem_Free(pixels);
3345                 pixels = NULL;
3346         }
3347
3348         mymiplevel = savemiplevel;
3349         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3350         {
3351                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3352                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3353                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3354                 Mem_Free(pixels);
3355                 pixels = NULL;
3356         }
3357
3358         if (basepixels)
3359                 Mem_Free(basepixels);
3360
3361         return skinframe;
3362 }
3363
3364 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3365 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3366 {
3367         int i;
3368         unsigned char *temp1, *temp2;
3369         skinframe_t *skinframe;
3370
3371         if (cls.state == ca_dedicated)
3372                 return NULL;
3373
3374         // if already loaded just return it, otherwise make a new skinframe
3375         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3376         if (skinframe && skinframe->base)
3377                 return skinframe;
3378
3379         skinframe->stain = NULL;
3380         skinframe->merged = NULL;
3381         skinframe->base = NULL;
3382         skinframe->pants = NULL;
3383         skinframe->shirt = NULL;
3384         skinframe->nmap = NULL;
3385         skinframe->gloss = NULL;
3386         skinframe->glow = NULL;
3387         skinframe->fog = NULL;
3388         skinframe->reflect = NULL;
3389         skinframe->hasalpha = false;
3390
3391         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3392         if (!skindata)
3393                 return NULL;
3394
3395         if (developer_loading.integer)
3396                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3397
3398         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3399         {
3400                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3401                 temp2 = temp1 + width * height * 4;
3402                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3403                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3404                 Mem_Free(temp1);
3405         }
3406         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3407         if (textureflags & TEXF_ALPHA)
3408         {
3409                 for (i = 3;i < width * height * 4;i += 4)
3410                 {
3411                         if (skindata[i] < 255)
3412                         {
3413                                 skinframe->hasalpha = true;
3414                                 break;
3415                         }
3416                 }
3417                 if (r_loadfog && skinframe->hasalpha)
3418                 {
3419                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3420                         memcpy(fogpixels, skindata, width * height * 4);
3421                         for (i = 0;i < width * height * 4;i += 4)
3422                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3423                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3424                         Mem_Free(fogpixels);
3425                 }
3426         }
3427
3428         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3429         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3430
3431         return skinframe;
3432 }
3433
3434 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3435 {
3436         int i;
3437         int featuresmask;
3438         skinframe_t *skinframe;
3439
3440         if (cls.state == ca_dedicated)
3441                 return NULL;
3442
3443         // if already loaded just return it, otherwise make a new skinframe
3444         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3445         if (skinframe && skinframe->base)
3446                 return skinframe;
3447
3448         skinframe->stain = NULL;
3449         skinframe->merged = NULL;
3450         skinframe->base = NULL;
3451         skinframe->pants = NULL;
3452         skinframe->shirt = NULL;
3453         skinframe->nmap = NULL;
3454         skinframe->gloss = NULL;
3455         skinframe->glow = NULL;
3456         skinframe->fog = NULL;
3457         skinframe->reflect = NULL;
3458         skinframe->hasalpha = false;
3459
3460         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3461         if (!skindata)
3462                 return NULL;
3463
3464         if (developer_loading.integer)
3465                 Con_Printf("loading quake skin \"%s\"\n", name);
3466
3467         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3468         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3469         memcpy(skinframe->qpixels, skindata, width*height);
3470         skinframe->qwidth = width;
3471         skinframe->qheight = height;
3472
3473         featuresmask = 0;
3474         for (i = 0;i < width * height;i++)
3475                 featuresmask |= palette_featureflags[skindata[i]];
3476
3477         skinframe->hasalpha = false;
3478         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3479         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3480         skinframe->qgeneratemerged = true;
3481         skinframe->qgeneratebase = skinframe->qhascolormapping;
3482         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3483
3484         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3485         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3486
3487         return skinframe;
3488 }
3489
3490 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3491 {
3492         int width;
3493         int height;
3494         unsigned char *skindata;
3495
3496         if (!skinframe->qpixels)
3497                 return;
3498
3499         if (!skinframe->qhascolormapping)
3500                 colormapped = false;
3501
3502         if (colormapped)
3503         {
3504                 if (!skinframe->qgeneratebase)
3505                         return;
3506         }
3507         else
3508         {
3509                 if (!skinframe->qgeneratemerged)
3510                         return;
3511         }
3512
3513         width = skinframe->qwidth;
3514         height = skinframe->qheight;
3515         skindata = skinframe->qpixels;
3516
3517         if (skinframe->qgeneratenmap)
3518         {
3519                 unsigned char *temp1, *temp2;
3520                 skinframe->qgeneratenmap = false;
3521                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3522                 temp2 = temp1 + width * height * 4;
3523                 // use either a custom palette or the quake palette
3524                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3525                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3526                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3527                 Mem_Free(temp1);
3528         }
3529
3530         if (skinframe->qgenerateglow)
3531         {
3532                 skinframe->qgenerateglow = false;
3533                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3534         }
3535
3536         if (colormapped)
3537         {
3538                 skinframe->qgeneratebase = false;
3539                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3540                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3541                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3542         }
3543         else
3544         {
3545                 skinframe->qgeneratemerged = false;
3546                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3547         }
3548
3549         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3550         {
3551                 Mem_Free(skinframe->qpixels);
3552                 skinframe->qpixels = NULL;
3553         }
3554 }
3555
3556 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3557 {
3558         int i;
3559         skinframe_t *skinframe;
3560
3561         if (cls.state == ca_dedicated)
3562                 return NULL;
3563
3564         // if already loaded just return it, otherwise make a new skinframe
3565         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3566         if (skinframe && skinframe->base)
3567                 return skinframe;
3568
3569         skinframe->stain = NULL;
3570         skinframe->merged = NULL;
3571         skinframe->base = NULL;
3572         skinframe->pants = NULL;
3573         skinframe->shirt = NULL;
3574         skinframe->nmap = NULL;
3575         skinframe->gloss = NULL;
3576         skinframe->glow = NULL;
3577         skinframe->fog = NULL;
3578         skinframe->reflect = NULL;
3579         skinframe->hasalpha = false;
3580
3581         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3582         if (!skindata)
3583                 return NULL;
3584
3585         if (developer_loading.integer)
3586                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3587
3588         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3589         if (textureflags & TEXF_ALPHA)
3590         {
3591                 for (i = 0;i < width * height;i++)
3592                 {
3593                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3594                         {
3595                                 skinframe->hasalpha = true;
3596                                 break;
3597                         }
3598                 }
3599                 if (r_loadfog && skinframe->hasalpha)
3600                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3601         }
3602
3603         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3604         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3605
3606         return skinframe;
3607 }
3608
3609 skinframe_t *R_SkinFrame_LoadMissing(void)
3610 {
3611         skinframe_t *skinframe;
3612
3613         if (cls.state == ca_dedicated)
3614                 return NULL;
3615
3616         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3617         skinframe->stain = NULL;
3618         skinframe->merged = NULL;
3619         skinframe->base = NULL;
3620         skinframe->pants = NULL;
3621         skinframe->shirt = NULL;
3622         skinframe->nmap = NULL;
3623         skinframe->gloss = NULL;
3624         skinframe->glow = NULL;
3625         skinframe->fog = NULL;
3626         skinframe->reflect = NULL;
3627         skinframe->hasalpha = false;
3628
3629         skinframe->avgcolor[0] = rand() / RAND_MAX;
3630         skinframe->avgcolor[1] = rand() / RAND_MAX;
3631         skinframe->avgcolor[2] = rand() / RAND_MAX;
3632         skinframe->avgcolor[3] = 1;
3633
3634         return skinframe;
3635 }
3636
3637 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3638 typedef struct suffixinfo_s
3639 {
3640         const char *suffix;
3641         qboolean flipx, flipy, flipdiagonal;
3642 }
3643 suffixinfo_t;
3644 static suffixinfo_t suffix[3][6] =
3645 {
3646         {
3647                 {"px",   false, false, false},
3648                 {"nx",   false, false, false},
3649                 {"py",   false, false, false},
3650                 {"ny",   false, false, false},
3651                 {"pz",   false, false, false},
3652                 {"nz",   false, false, false}
3653         },
3654         {
3655                 {"posx", false, false, false},
3656                 {"negx", false, false, false},
3657                 {"posy", false, false, false},
3658                 {"negy", false, false, false},
3659                 {"posz", false, false, false},
3660                 {"negz", false, false, false}
3661         },
3662         {
3663                 {"rt",    true, false,  true},
3664                 {"lf",   false,  true,  true},
3665                 {"ft",    true,  true, false},
3666                 {"bk",   false, false, false},
3667                 {"up",    true, false,  true},
3668                 {"dn",    true, false,  true}
3669         }
3670 };
3671
3672 static int componentorder[4] = {0, 1, 2, 3};
3673
3674 rtexture_t *R_LoadCubemap(const char *basename)
3675 {
3676         int i, j, cubemapsize;
3677         unsigned char *cubemappixels, *image_buffer;
3678         rtexture_t *cubemaptexture;
3679         char name[256];
3680         // must start 0 so the first loadimagepixels has no requested width/height
3681         cubemapsize = 0;
3682         cubemappixels = NULL;
3683         cubemaptexture = NULL;
3684         // keep trying different suffix groups (posx, px, rt) until one loads
3685         for (j = 0;j < 3 && !cubemappixels;j++)
3686         {
3687                 // load the 6 images in the suffix group
3688                 for (i = 0;i < 6;i++)
3689                 {
3690                         // generate an image name based on the base and and suffix
3691                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3692                         // load it
3693                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3694                         {
3695                                 // an image loaded, make sure width and height are equal
3696                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3697                                 {
3698                                         // if this is the first image to load successfully, allocate the cubemap memory
3699                                         if (!cubemappixels && image_width >= 1)
3700                                         {
3701                                                 cubemapsize = image_width;
3702                                                 // note this clears to black, so unavailable sides are black
3703                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3704                                         }
3705                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3706                                         if (cubemappixels)
3707                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3708                                 }
3709                                 else
3710                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3711                                 // free the image
3712                                 Mem_Free(image_buffer);
3713                         }
3714                 }
3715         }
3716         // if a cubemap loaded, upload it
3717         if (cubemappixels)
3718         {
3719                 if (developer_loading.integer)
3720                         Con_Printf("loading cubemap \"%s\"\n", basename);
3721
3722                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3723                 Mem_Free(cubemappixels);
3724         }
3725         else
3726         {
3727                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3728                 if (developer_loading.integer)
3729                 {
3730                         Con_Printf("(tried tried images ");
3731                         for (j = 0;j < 3;j++)
3732                                 for (i = 0;i < 6;i++)
3733                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3734                         Con_Print(" and was unable to find any of them).\n");
3735                 }
3736         }
3737         return cubemaptexture;
3738 }
3739
3740 rtexture_t *R_GetCubemap(const char *basename)
3741 {
3742         int i;
3743         for (i = 0;i < r_texture_numcubemaps;i++)
3744                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3745                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3746         if (i >= MAX_CUBEMAPS)
3747                 return r_texture_whitecube;
3748         r_texture_numcubemaps++;
3749         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3750         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3751         return r_texture_cubemaps[i].texture;
3752 }
3753
3754 void R_FreeCubemaps(void)
3755 {
3756         int i;
3757         for (i = 0;i < r_texture_numcubemaps;i++)
3758         {
3759                 if (developer_loading.integer)
3760                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3761                 if (r_texture_cubemaps[i].texture)
3762                         R_FreeTexture(r_texture_cubemaps[i].texture);
3763         }
3764         r_texture_numcubemaps = 0;
3765 }
3766
3767 void R_Main_FreeViewCache(void)
3768 {
3769         if (r_refdef.viewcache.entityvisible)
3770                 Mem_Free(r_refdef.viewcache.entityvisible);
3771         if (r_refdef.viewcache.world_pvsbits)
3772                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3773         if (r_refdef.viewcache.world_leafvisible)
3774                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3775         if (r_refdef.viewcache.world_surfacevisible)
3776                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3777         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3778 }
3779
3780 void R_Main_ResizeViewCache(void)
3781 {
3782         int numentities = r_refdef.scene.numentities;
3783         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3784         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3785         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3786         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3787         if (r_refdef.viewcache.maxentities < numentities)
3788         {
3789                 r_refdef.viewcache.maxentities = numentities;
3790                 if (r_refdef.viewcache.entityvisible)
3791                         Mem_Free(r_refdef.viewcache.entityvisible);
3792                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3793         }
3794         if (r_refdef.viewcache.world_numclusters != numclusters)
3795         {
3796                 r_refdef.viewcache.world_numclusters = numclusters;
3797                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3798                 if (r_refdef.viewcache.world_pvsbits)
3799                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3800                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3801         }
3802         if (r_refdef.viewcache.world_numleafs != numleafs)
3803         {
3804                 r_refdef.viewcache.world_numleafs = numleafs;
3805                 if (r_refdef.viewcache.world_leafvisible)
3806                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3807                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3808         }
3809         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3810         {
3811                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3812                 if (r_refdef.viewcache.world_surfacevisible)
3813                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3814                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3815         }
3816 }
3817
3818 extern rtexture_t *loadingscreentexture;
3819 void gl_main_start(void)
3820 {
3821         loadingscreentexture = NULL;
3822         r_texture_blanknormalmap = NULL;
3823         r_texture_white = NULL;
3824         r_texture_grey128 = NULL;
3825         r_texture_black = NULL;
3826         r_texture_whitecube = NULL;
3827         r_texture_normalizationcube = NULL;
3828         r_texture_fogattenuation = NULL;
3829         r_texture_fogheighttexture = NULL;
3830         r_texture_gammaramps = NULL;
3831         r_texture_numcubemaps = 0;
3832
3833         r_loaddds = r_texture_dds_load.integer != 0;
3834         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3835
3836         switch(vid.renderpath)
3837         {
3838         case RENDERPATH_GL20:
3839         case RENDERPATH_D3D9:
3840         case RENDERPATH_D3D10:
3841         case RENDERPATH_D3D11:
3842         case RENDERPATH_SOFT:
3843         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                 if(vid.renderpath != RENDERPATH_SOFT) 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         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5175         {
5176                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5177                 float screenplane[4];
5178                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5179                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5180                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5181                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5182                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5183         }
5184 }
5185
5186 void R_EntityMatrix(const matrix4x4_t *matrix)
5187 {
5188         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5189         {
5190                 gl_modelmatrixchanged = false;
5191                 gl_modelmatrix = *matrix;
5192                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5193                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5194                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5195                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5196                 CHECKGLERROR
5197                 switch(vid.renderpath)
5198                 {
5199                 case RENDERPATH_D3D9:
5200 #ifdef SUPPORTD3D
5201                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5202                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5203 #endif
5204                         break;
5205                 case RENDERPATH_D3D10:
5206                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5207                         break;
5208                 case RENDERPATH_D3D11:
5209                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5210                         break;
5211                 case RENDERPATH_GL13:
5212                 case RENDERPATH_GL11:
5213                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5214                         break;
5215                 case RENDERPATH_SOFT:
5216                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5217                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5218                         break;
5219                 case RENDERPATH_GL20:
5220                 case RENDERPATH_GLES2:
5221                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5222                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5223                         break;
5224                 }
5225         }
5226 }
5227
5228 void R_ResetViewRendering2D(void)
5229 {
5230         r_viewport_t viewport;
5231         DrawQ_Finish();
5232
5233         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5234         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);
5235         R_Mesh_ResetRenderTargets();
5236         R_SetViewport(&viewport);
5237         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5238         GL_Color(1, 1, 1, 1);
5239         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5240         GL_BlendFunc(GL_ONE, GL_ZERO);
5241         GL_ScissorTest(false);
5242         GL_DepthMask(false);
5243         GL_DepthRange(0, 1);
5244         GL_DepthTest(false);
5245         GL_DepthFunc(GL_LEQUAL);
5246         R_EntityMatrix(&identitymatrix);
5247         R_Mesh_ResetTextureState();
5248         GL_PolygonOffset(0, 0);
5249         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5250         switch(vid.renderpath)
5251         {
5252         case RENDERPATH_GL11:
5253         case RENDERPATH_GL13:
5254         case RENDERPATH_GL20:
5255         case RENDERPATH_GLES2:
5256                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5257                 break;
5258         case RENDERPATH_D3D9:
5259         case RENDERPATH_D3D10:
5260         case RENDERPATH_D3D11:
5261         case RENDERPATH_SOFT:
5262                 break;
5263         }
5264         GL_CullFace(GL_NONE);
5265 }
5266
5267 void R_ResetViewRendering3D(void)
5268 {
5269         DrawQ_Finish();
5270
5271         R_SetupView(true);
5272         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5273         GL_Color(1, 1, 1, 1);
5274         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5275         GL_BlendFunc(GL_ONE, GL_ZERO);
5276         GL_ScissorTest(true);
5277         GL_DepthMask(true);
5278         GL_DepthRange(0, 1);
5279         GL_DepthTest(true);
5280         GL_DepthFunc(GL_LEQUAL);
5281         R_EntityMatrix(&identitymatrix);
5282         R_Mesh_ResetTextureState();
5283         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5284         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5285         switch(vid.renderpath)
5286         {
5287         case RENDERPATH_GL11:
5288         case RENDERPATH_GL13:
5289         case RENDERPATH_GL20:
5290         case RENDERPATH_GLES2:
5291                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5292                 break;
5293         case RENDERPATH_D3D9:
5294         case RENDERPATH_D3D10:
5295         case RENDERPATH_D3D11:
5296         case RENDERPATH_SOFT:
5297                 break;
5298         }
5299         GL_CullFace(r_refdef.view.cullface_back);
5300 }
5301
5302 /*
5303 ================
5304 R_RenderView_UpdateViewVectors
5305 ================
5306 */
5307 static void R_RenderView_UpdateViewVectors(void)
5308 {
5309         // break apart the view matrix into vectors for various purposes
5310         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5311         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5312         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5313         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5314         // make an inverted copy of the view matrix for tracking sprites
5315         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5316 }
5317
5318 void R_RenderScene(void);
5319 void R_RenderWaterPlanes(void);
5320
5321 static void R_Water_StartFrame(void)
5322 {
5323         int i;
5324         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5325         r_waterstate_waterplane_t *p;
5326
5327         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5328                 return;
5329
5330         switch(vid.renderpath)
5331         {
5332         case RENDERPATH_GL20:
5333         case RENDERPATH_D3D9:
5334         case RENDERPATH_D3D10:
5335         case RENDERPATH_D3D11:
5336         case RENDERPATH_SOFT:
5337         case RENDERPATH_GLES2:
5338                 break;
5339         case RENDERPATH_GL13:
5340         case RENDERPATH_GL11:
5341                 return;
5342         }
5343
5344         // set waterwidth and waterheight to the water resolution that will be
5345         // used (often less than the screen resolution for faster rendering)
5346         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5347         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5348
5349         // calculate desired texture sizes
5350         // can't use water if the card does not support the texture size
5351         if (!r_water.integer || r_showsurfaces.integer)
5352                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5353         else if (vid.support.arb_texture_non_power_of_two)
5354         {
5355                 texturewidth = waterwidth;
5356                 textureheight = waterheight;
5357                 camerawidth = waterwidth;
5358                 cameraheight = waterheight;
5359         }
5360         else
5361         {
5362                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5363                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5364                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5365                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5366         }
5367
5368         // allocate textures as needed
5369         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5370         {
5371                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5372                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5373                 {
5374                         if (p->texture_refraction)
5375                                 R_FreeTexture(p->texture_refraction);
5376                         p->texture_refraction = NULL;
5377                         if (p->texture_reflection)
5378                                 R_FreeTexture(p->texture_reflection);
5379                         p->texture_reflection = NULL;
5380                         if (p->texture_camera)
5381                                 R_FreeTexture(p->texture_camera);
5382                         p->texture_camera = NULL;
5383                 }
5384                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5385                 r_waterstate.texturewidth = texturewidth;
5386                 r_waterstate.textureheight = textureheight;
5387                 r_waterstate.camerawidth = camerawidth;
5388                 r_waterstate.cameraheight = cameraheight;
5389         }
5390
5391         if (r_waterstate.texturewidth)
5392         {
5393                 r_waterstate.enabled = true;
5394
5395                 // when doing a reduced render (HDR) we want to use a smaller area
5396                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5397                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5398
5399                 // set up variables that will be used in shader setup
5400                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5401                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5402                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5403                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5404         }
5405
5406         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5407         r_waterstate.numwaterplanes = 0;
5408 }
5409
5410 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5411 {
5412         int triangleindex, planeindex;
5413         const int *e;
5414         vec3_t vert[3];
5415         vec3_t normal;
5416         vec3_t center;
5417         mplane_t plane;
5418         r_waterstate_waterplane_t *p;
5419         texture_t *t = R_GetCurrentTexture(surface->texture);
5420
5421         // just use the first triangle with a valid normal for any decisions
5422         VectorClear(normal);
5423         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5424         {
5425                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5426                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5427                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5428                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5429                 if (VectorLength2(normal) >= 0.001)
5430                         break;
5431         }
5432
5433         VectorCopy(normal, plane.normal);
5434         VectorNormalize(plane.normal);
5435         plane.dist = DotProduct(vert[0], plane.normal);
5436         PlaneClassify(&plane);
5437         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5438         {
5439                 // skip backfaces (except if nocullface is set)
5440                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5441                         return;
5442                 VectorNegate(plane.normal, plane.normal);
5443                 plane.dist *= -1;
5444                 PlaneClassify(&plane);
5445         }
5446
5447
5448         // find a matching plane if there is one
5449         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5450                 if(p->camera_entity == t->camera_entity)
5451                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5452                                 break;
5453         if (planeindex >= r_waterstate.maxwaterplanes)
5454                 return; // nothing we can do, out of planes
5455
5456         // if this triangle does not fit any known plane rendered this frame, add one
5457         if (planeindex >= r_waterstate.numwaterplanes)
5458         {
5459                 // store the new plane
5460                 r_waterstate.numwaterplanes++;
5461                 p->plane = plane;
5462                 // clear materialflags and pvs
5463                 p->materialflags = 0;
5464                 p->pvsvalid = false;
5465                 p->camera_entity = t->camera_entity;
5466                 VectorCopy(surface->mins, p->mins);
5467                 VectorCopy(surface->maxs, p->maxs);
5468         }
5469         else
5470         {
5471                 // merge mins/maxs
5472                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5473                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5474                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5475                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5476                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5477                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5478         }
5479         // merge this surface's materialflags into the waterplane
5480         p->materialflags |= t->currentmaterialflags;
5481         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5482         {
5483                 // merge this surface's PVS into the waterplane
5484                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5485                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5486                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5487                 {
5488                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5489                         p->pvsvalid = true;
5490                 }
5491         }
5492 }
5493
5494 static void R_Water_ProcessPlanes(void)
5495 {
5496         int myscissor[4];
5497         r_refdef_view_t originalview;
5498         r_refdef_view_t myview;
5499         int planeindex;
5500         r_waterstate_waterplane_t *p;
5501         vec3_t visorigin;
5502
5503         originalview = r_refdef.view;
5504
5505         // make sure enough textures are allocated
5506         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5507         {
5508                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5509                 {
5510                         if (!p->texture_refraction)
5511                                 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);
5512                         if (!p->texture_refraction)
5513                                 goto error;
5514                 }
5515                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5516                 {
5517                         if (!p->texture_camera)
5518                                 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);
5519                         if (!p->texture_camera)
5520                                 goto error;
5521                 }
5522
5523                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5524                 {
5525                         if (!p->texture_reflection)
5526                                 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);
5527                         if (!p->texture_reflection)
5528                                 goto error;
5529                 }
5530         }
5531
5532         // render views
5533         r_refdef.view = originalview;
5534         r_refdef.view.showdebug = false;
5535         r_refdef.view.width = r_waterstate.waterwidth;
5536         r_refdef.view.height = r_waterstate.waterheight;
5537         r_refdef.view.useclipplane = true;
5538         myview = r_refdef.view;
5539         r_waterstate.renderingscene = true;
5540         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5541         {
5542                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5543                 {
5544                         r_refdef.view = myview;
5545                         if(r_water_scissormode.integer)
5546                         {
5547                                 R_SetupView(true);
5548                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5549                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5550                         }
5551
5552                         // render reflected scene and copy into texture
5553                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5554                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5555                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5556                         r_refdef.view.clipplane = p->plane;
5557
5558                         // reverse the cullface settings for this render
5559                         r_refdef.view.cullface_front = GL_FRONT;
5560                         r_refdef.view.cullface_back = GL_BACK;
5561                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5562                         {
5563                                 r_refdef.view.usecustompvs = true;
5564                                 if (p->pvsvalid)
5565                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5566                                 else
5567                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5568                         }
5569
5570                         R_ResetViewRendering3D();
5571                         R_ClearScreen(r_refdef.fogenabled);
5572                         if(r_water_scissormode.integer & 2)
5573                                 R_View_UpdateWithScissor(myscissor);
5574                         else
5575                                 R_View_Update();
5576                         if(r_water_scissormode.integer & 1)
5577                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5578                         R_RenderScene();
5579
5580                         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);
5581                 }
5582
5583                 // render the normal view scene and copy into texture
5584                 // (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)
5585                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5586                 {
5587                         r_refdef.view = myview;
5588                         if(r_water_scissormode.integer)
5589                         {
5590                                 R_SetupView(true);
5591                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5592                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5593                         }
5594
5595                         r_waterstate.renderingrefraction = true;
5596
5597                         r_refdef.view.clipplane = p->plane;
5598                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5599                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5600
5601                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5602                         {
5603                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5604                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5605                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5606                                 R_RenderView_UpdateViewVectors();
5607                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5608                                 {
5609                                         r_refdef.view.usecustompvs = true;
5610                                         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);
5611                                 }
5612                         }
5613
5614                         PlaneClassify(&r_refdef.view.clipplane);
5615
5616                         R_ResetViewRendering3D();
5617                         R_ClearScreen(r_refdef.fogenabled);
5618                         if(r_water_scissormode.integer & 2)
5619                                 R_View_UpdateWithScissor(myscissor);
5620                         else
5621                                 R_View_Update();
5622                         if(r_water_scissormode.integer & 1)
5623                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5624                         R_RenderScene();
5625
5626                         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);
5627                         r_waterstate.renderingrefraction = false;
5628                 }
5629                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5630                 {
5631                         r_refdef.view = myview;
5632
5633                         r_refdef.view.clipplane = p->plane;
5634                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5635                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5636
5637                         r_refdef.view.width = r_waterstate.camerawidth;
5638                         r_refdef.view.height = r_waterstate.cameraheight;
5639                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5640                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5641
5642                         if(p->camera_entity)
5643                         {
5644                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5645                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5646                         }
5647
5648                         // note: all of the view is used for displaying... so
5649                         // there is no use in scissoring
5650
5651                         // reverse the cullface settings for this render
5652                         r_refdef.view.cullface_front = GL_FRONT;
5653                         r_refdef.view.cullface_back = GL_BACK;
5654                         // also reverse the view matrix
5655                         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
5656                         R_RenderView_UpdateViewVectors();
5657                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5658                         {
5659                                 r_refdef.view.usecustompvs = true;
5660                                 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);
5661                         }
5662                         
5663                         // camera needs no clipplane
5664                         r_refdef.view.useclipplane = false;
5665
5666                         PlaneClassify(&r_refdef.view.clipplane);
5667
5668                         R_ResetViewRendering3D();
5669                         R_ClearScreen(r_refdef.fogenabled);
5670                         R_View_Update();
5671                         R_RenderScene();
5672
5673                         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);
5674                         r_waterstate.renderingrefraction = false;
5675                 }
5676
5677         }
5678         DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5679         r_waterstate.renderingscene = false;
5680         r_refdef.view = originalview;
5681         R_ResetViewRendering3D();
5682         R_ClearScreen(r_refdef.fogenabled);
5683         R_View_Update();
5684         return;
5685 error:
5686         r_refdef.view = originalview;
5687         r_waterstate.renderingscene = false;
5688         Cvar_SetValueQuick(&r_water, 0);
5689         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5690         return;
5691 }
5692
5693 void R_Bloom_StartFrame(void)
5694 {
5695         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5696         int viewwidth, viewheight;
5697         textype_t textype;
5698
5699         if (r_viewscale_fpsscaling.integer)
5700         {
5701                 double actualframetime;
5702                 double targetframetime;
5703                 double adjust;
5704                 actualframetime = r_refdef.lastdrawscreentime;
5705                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5706                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5707                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5708                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5709                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5710                 viewscalefpsadjusted += adjust;
5711                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5712         }
5713         else
5714                 viewscalefpsadjusted = 1.0f;
5715
5716         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5717
5718         switch(vid.renderpath)
5719         {
5720         case RENDERPATH_GL20:
5721         case RENDERPATH_D3D9:
5722         case RENDERPATH_D3D10:
5723         case RENDERPATH_D3D11:
5724         case RENDERPATH_SOFT:
5725         case RENDERPATH_GLES2:
5726                 break;
5727         case RENDERPATH_GL13:
5728         case RENDERPATH_GL11:
5729                 return;
5730         }
5731
5732         // set bloomwidth and bloomheight to the bloom resolution that will be
5733         // used (often less than the screen resolution for faster rendering)
5734         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5735         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5736         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5737         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5738         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5739
5740         // calculate desired texture sizes
5741         if (vid.support.arb_texture_non_power_of_two)
5742         {
5743                 screentexturewidth = vid.width;
5744                 screentextureheight = vid.height;
5745                 bloomtexturewidth = r_bloomstate.bloomwidth;
5746                 bloomtextureheight = r_bloomstate.bloomheight;
5747         }
5748         else
5749         {
5750                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5751                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5752                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5753                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5754         }
5755
5756         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))
5757         {
5758                 Cvar_SetValueQuick(&r_hdr, 0);
5759                 Cvar_SetValueQuick(&r_bloom, 0);
5760                 Cvar_SetValueQuick(&r_motionblur, 0);
5761                 Cvar_SetValueQuick(&r_damageblur, 0);
5762         }
5763
5764         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)
5765                 screentexturewidth = screentextureheight = 0;
5766         if (!r_hdr.integer && !r_bloom.integer)
5767                 bloomtexturewidth = bloomtextureheight = 0;
5768
5769         textype = TEXTYPE_COLORBUFFER;
5770         switch (vid.renderpath)
5771         {
5772         case RENDERPATH_GL20:
5773         case RENDERPATH_GLES2:
5774                 if (vid.support.ext_framebuffer_object)
5775                 {
5776                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5777                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5778                 }
5779                 break;
5780         case RENDERPATH_D3D9:
5781         case RENDERPATH_D3D10:
5782         case RENDERPATH_D3D11:
5783         case RENDERPATH_SOFT:
5784         case RENDERPATH_GL13:
5785         case RENDERPATH_GL11:
5786                 break;
5787         }
5788
5789         // allocate textures as needed
5790         if (r_bloomstate.screentexturewidth != screentexturewidth
5791          || r_bloomstate.screentextureheight != screentextureheight
5792          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5793          || r_bloomstate.bloomtextureheight != bloomtextureheight
5794          || r_bloomstate.texturetype != textype
5795          || r_bloomstate.viewfbo != r_viewfbo.integer)
5796         {
5797                 if (r_bloomstate.texture_bloom)
5798                         R_FreeTexture(r_bloomstate.texture_bloom);
5799                 r_bloomstate.texture_bloom = NULL;
5800                 if (r_bloomstate.texture_screen)
5801                         R_FreeTexture(r_bloomstate.texture_screen);
5802                 r_bloomstate.texture_screen = NULL;
5803                 if (r_bloomstate.fbo_framebuffer)
5804                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5805                 r_bloomstate.fbo_framebuffer = 0;
5806                 if (r_bloomstate.texture_framebuffercolor)
5807                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5808                 r_bloomstate.texture_framebuffercolor = NULL;
5809                 if (r_bloomstate.texture_framebufferdepth)
5810                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5811                 r_bloomstate.texture_framebufferdepth = NULL;
5812                 r_bloomstate.screentexturewidth = screentexturewidth;
5813                 r_bloomstate.screentextureheight = screentextureheight;
5814                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5815                         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);
5816                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5817                 {
5818                         // FIXME: choose depth bits based on a cvar
5819                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5820                         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);
5821                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5822                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5823                         // render depth into one texture and normalmap into the other
5824                         if (qglDrawBuffer)
5825                         {
5826                                 int status;
5827                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5828                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5829                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5830                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5831                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5832                         }
5833                 }
5834                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5835                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5836                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5837                         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);
5838                 r_bloomstate.viewfbo = r_viewfbo.integer;
5839                 r_bloomstate.texturetype = textype;
5840         }
5841
5842         // when doing a reduced render (HDR) we want to use a smaller area
5843         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5844         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5845         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5846         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5847         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5848
5849         // set up a texcoord array for the full resolution screen image
5850         // (we have to keep this around to copy back during final render)
5851         r_bloomstate.screentexcoord2f[0] = 0;
5852         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5853         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5854         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5855         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5856         r_bloomstate.screentexcoord2f[5] = 0;
5857         r_bloomstate.screentexcoord2f[6] = 0;
5858         r_bloomstate.screentexcoord2f[7] = 0;
5859
5860         // set up a texcoord array for the reduced resolution bloom image
5861         // (which will be additive blended over the screen image)
5862         r_bloomstate.bloomtexcoord2f[0] = 0;
5863         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5864         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5865         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5866         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5867         r_bloomstate.bloomtexcoord2f[5] = 0;
5868         r_bloomstate.bloomtexcoord2f[6] = 0;
5869         r_bloomstate.bloomtexcoord2f[7] = 0;
5870
5871         switch(vid.renderpath)
5872         {
5873         case RENDERPATH_GL11:
5874         case RENDERPATH_GL13:
5875         case RENDERPATH_GL20:
5876         case RENDERPATH_SOFT:
5877         case RENDERPATH_GLES2:
5878                 break;
5879         case RENDERPATH_D3D9:
5880         case RENDERPATH_D3D10:
5881         case RENDERPATH_D3D11:
5882                 {
5883                         int i;
5884                         for (i = 0;i < 4;i++)
5885                         {
5886                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5887                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5888                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5889                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5890                         }
5891                 }
5892                 break;
5893         }
5894
5895         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5896         {
5897                 r_bloomstate.enabled = true;
5898                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5899         }
5900
5901         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);
5902
5903         if (r_bloomstate.fbo_framebuffer)
5904                 r_refdef.view.clear = true;
5905 }
5906
5907 void R_Bloom_CopyBloomTexture(float colorscale)
5908 {
5909         r_refdef.stats.bloom++;
5910
5911         // scale down screen texture to the bloom texture size
5912         CHECKGLERROR
5913         R_Mesh_SetMainRenderTargets();
5914         R_SetViewport(&r_bloomstate.viewport);
5915         GL_BlendFunc(GL_ONE, GL_ZERO);
5916         GL_Color(colorscale, colorscale, colorscale, 1);
5917         // 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...
5918         switch(vid.renderpath)
5919         {
5920         case RENDERPATH_GL11:
5921         case RENDERPATH_GL13:
5922         case RENDERPATH_GL20:
5923         case RENDERPATH_SOFT:
5924         case RENDERPATH_GLES2:
5925                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5926                 break;
5927         case RENDERPATH_D3D9:
5928         case RENDERPATH_D3D10:
5929         case RENDERPATH_D3D11:
5930                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5931                 break;
5932         }
5933         // TODO: do boxfilter scale-down in shader?
5934         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5935         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5936         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5937
5938         // we now have a bloom image in the framebuffer
5939         // copy it into the bloom image texture for later processing
5940         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);
5941         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5942 }
5943
5944 void R_Bloom_CopyHDRTexture(void)
5945 {
5946         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);
5947         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5948 }
5949
5950 void R_Bloom_MakeTexture(void)
5951 {
5952         int x, range, dir;
5953         float xoffset, yoffset, r, brighten;
5954
5955         r_refdef.stats.bloom++;
5956
5957         R_ResetViewRendering2D();
5958
5959         // we have a bloom image in the framebuffer
5960         CHECKGLERROR
5961         R_SetViewport(&r_bloomstate.viewport);
5962
5963         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5964         {
5965                 x *= 2;
5966                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5967                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5968                 GL_Color(r,r,r,1);
5969                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5970                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5971                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5972                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5973
5974                 // copy the vertically blurred bloom view to a texture
5975                 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);
5976                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5977         }
5978
5979         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5980         brighten = r_bloom_brighten.value;
5981         if (r_bloomstate.hdr)
5982                 brighten *= r_hdr_range.value;
5983         brighten = sqrt(brighten);
5984         if(range >= 1)
5985                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5986         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5987
5988         for (dir = 0;dir < 2;dir++)
5989         {
5990                 // blend on at multiple vertical offsets to achieve a vertical blur
5991                 // TODO: do offset blends using GLSL
5992                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5993                 GL_BlendFunc(GL_ONE, GL_ZERO);
5994                 for (x = -range;x <= range;x++)
5995                 {
5996                         if (!dir){xoffset = 0;yoffset = x;}
5997                         else {xoffset = x;yoffset = 0;}
5998                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5999                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6000                         // compute a texcoord array with the specified x and y offset
6001                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6002                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6003                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6004                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6005                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6006                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6007                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6008                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6009                         // this r value looks like a 'dot' particle, fading sharply to
6010                         // black at the edges
6011                         // (probably not realistic but looks good enough)
6012                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6013                         //r = brighten/(range*2+1);
6014                         r = brighten / (range * 2 + 1);
6015                         if(range >= 1)
6016                                 r *= (1 - x*x/(float)(range*range));
6017                         GL_Color(r, r, r, 1);
6018                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6019                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6020                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6021                         GL_BlendFunc(GL_ONE, GL_ONE);
6022                 }
6023
6024                 // copy the vertically blurred bloom view to a texture
6025                 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);
6026                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6027         }
6028 }
6029
6030 void R_HDR_RenderBloomTexture(void)
6031 {
6032         int oldwidth, oldheight;
6033         float oldcolorscale;
6034         qboolean oldwaterstate;
6035
6036         oldwaterstate = r_waterstate.enabled;
6037         oldcolorscale = r_refdef.view.colorscale;
6038         oldwidth = r_refdef.view.width;
6039         oldheight = r_refdef.view.height;
6040         r_refdef.view.width = r_bloomstate.bloomwidth;
6041         r_refdef.view.height = r_bloomstate.bloomheight;
6042
6043         if(r_hdr.integer < 2)
6044                 r_waterstate.enabled = false;
6045
6046         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6047         // TODO: add exposure compensation features
6048         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6049
6050         r_refdef.view.showdebug = false;
6051         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6052
6053         R_ResetViewRendering3D();
6054
6055         R_ClearScreen(r_refdef.fogenabled);
6056         if (r_timereport_active)
6057                 R_TimeReport("HDRclear");
6058
6059         R_View_Update();
6060         if (r_timereport_active)
6061                 R_TimeReport("visibility");
6062
6063         // only do secondary renders with HDR if r_hdr is 2 or higher
6064         r_waterstate.numwaterplanes = 0;
6065         if (r_waterstate.enabled)
6066                 R_RenderWaterPlanes();
6067
6068         r_refdef.view.showdebug = true;
6069         R_RenderScene();
6070         r_waterstate.numwaterplanes = 0;
6071
6072         R_ResetViewRendering2D();
6073
6074         R_Bloom_CopyHDRTexture();
6075         R_Bloom_MakeTexture();
6076
6077         // restore the view settings
6078         r_waterstate.enabled = oldwaterstate;
6079         r_refdef.view.width = oldwidth;
6080         r_refdef.view.height = oldheight;
6081         r_refdef.view.colorscale = oldcolorscale;
6082
6083         R_ResetViewRendering3D();
6084
6085         R_ClearScreen(r_refdef.fogenabled);
6086         if (r_timereport_active)
6087                 R_TimeReport("viewclear");
6088 }
6089
6090 static void R_BlendView(void)
6091 {
6092         unsigned int permutation;
6093         float uservecs[4][4];
6094
6095         switch (vid.renderpath)
6096         {
6097         case RENDERPATH_GL20:
6098         case RENDERPATH_D3D9:
6099         case RENDERPATH_D3D10:
6100         case RENDERPATH_D3D11:
6101         case RENDERPATH_SOFT:
6102         case RENDERPATH_GLES2:
6103                 permutation =
6104                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6105                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6106                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6107                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6108                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6109
6110                 if (r_bloomstate.texture_screen)
6111                 {
6112                         // make sure the buffer is available
6113                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6114
6115                         R_ResetViewRendering2D();
6116                         R_Mesh_SetMainRenderTargets();
6117
6118                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6119                         {
6120                                 // declare variables
6121                                 float speed;
6122                                 static float avgspeed;
6123
6124                                 speed = VectorLength(cl.movement_velocity);
6125
6126                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6127                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6128
6129                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6130                                 speed = bound(0, speed, 1);
6131                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6132
6133                                 // calculate values into a standard alpha
6134                                 cl.motionbluralpha = 1 - exp(-
6135                                                 (
6136                                                  (r_motionblur.value * speed / 80)
6137                                                  +
6138                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6139                                                 )
6140                                                 /
6141                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6142                                            );
6143
6144                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6145                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6146                                 // apply the blur
6147                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6148                                 {
6149                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6150                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6151                                         switch(vid.renderpath)
6152                                         {
6153                                         case RENDERPATH_GL11:
6154                                         case RENDERPATH_GL13:
6155                                         case RENDERPATH_GL20:
6156                                         case RENDERPATH_SOFT:
6157                                         case RENDERPATH_GLES2:
6158                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6159                                                 break;
6160                                         case RENDERPATH_D3D9:
6161                                         case RENDERPATH_D3D10:
6162                                         case RENDERPATH_D3D11:
6163                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6164                                                 break;
6165                                         }
6166                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6167                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6168                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6169                                 }
6170                         }
6171
6172                         // copy view into the screen texture
6173                         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);
6174                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6175                 }
6176                 else if (!r_bloomstate.texture_bloom)
6177                 {
6178                         // we may still have to do view tint...
6179                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6180                         {
6181                                 // apply a color tint to the whole view
6182                                 R_ResetViewRendering2D();
6183                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6184                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6185                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6186                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6187                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6188                         }
6189                         break; // no screen processing, no bloom, skip it
6190                 }
6191
6192                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6193                 {
6194                         // render simple bloom effect
6195                         // copy the screen and shrink it and darken it for the bloom process
6196                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6197                         // make the bloom texture
6198                         R_Bloom_MakeTexture();
6199                 }
6200
6201 #if _MSC_VER >= 1400
6202 #define sscanf sscanf_s
6203 #endif
6204                 memset(uservecs, 0, sizeof(uservecs));
6205                 if (r_glsl_postprocess_uservec1_enable.integer)
6206                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6207                 if (r_glsl_postprocess_uservec2_enable.integer)
6208                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6209                 if (r_glsl_postprocess_uservec3_enable.integer)
6210                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6211                 if (r_glsl_postprocess_uservec4_enable.integer)
6212                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6213
6214                 R_ResetViewRendering2D();
6215                 GL_Color(1, 1, 1, 1);
6216                 GL_BlendFunc(GL_ONE, GL_ZERO);
6217
6218                 switch(vid.renderpath)
6219                 {
6220                 case RENDERPATH_GL20:
6221                 case RENDERPATH_GLES2:
6222                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6223                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6224                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6225                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6226                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6227                         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]);
6228                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6229                         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]);
6230                         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]);
6231                         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]);
6232                         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]);
6233                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6234                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6235                         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);
6236                         break;
6237                 case RENDERPATH_D3D9:
6238 #ifdef SUPPORTD3D
6239                         // 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...
6240                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6241                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6242                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6243                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6244                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6245                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6246                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6247                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6248                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6249                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6250                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6251                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6252                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6253                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6254 #endif
6255                         break;
6256                 case RENDERPATH_D3D10:
6257                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6258                         break;
6259                 case RENDERPATH_D3D11:
6260                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6261                         break;
6262                 case RENDERPATH_SOFT:
6263                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6264                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6265                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6266                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6267                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6268                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6269                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6270                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6271                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6272                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6273                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6274                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6275                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6276                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6277                         break;
6278                 default:
6279                         break;
6280                 }
6281                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6282                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6283                 break;
6284         case RENDERPATH_GL13:
6285         case RENDERPATH_GL11:
6286                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6287                 {
6288                         // apply a color tint to the whole view
6289                         R_ResetViewRendering2D();
6290                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6291                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6292                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6293                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6294                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6295                 }
6296                 break;
6297         }
6298 }
6299
6300 matrix4x4_t r_waterscrollmatrix;
6301
6302 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6303 {
6304         if (r_refdef.fog_density)
6305         {
6306                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6307                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6308                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6309
6310                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6311                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6312                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6313                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6314
6315                 {
6316                         vec3_t fogvec;
6317                         VectorCopy(r_refdef.fogcolor, fogvec);
6318                         //   color.rgb *= ContrastBoost * SceneBrightness;
6319                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6320                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6321                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6322                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6323                 }
6324         }
6325 }
6326
6327 void R_UpdateVariables(void)
6328 {
6329         R_Textures_Frame();
6330
6331         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6332
6333         r_refdef.farclip = r_farclip_base.value;
6334         if (r_refdef.scene.worldmodel)
6335                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6336         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6337
6338         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6339                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6340         r_refdef.polygonfactor = 0;
6341         r_refdef.polygonoffset = 0;
6342         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6343         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6344
6345         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6346         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6347         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6348         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6349         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6350         if (FAKELIGHT_ENABLED)
6351         {
6352                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6353         }
6354         if (r_showsurfaces.integer)
6355         {
6356                 r_refdef.scene.rtworld = false;
6357                 r_refdef.scene.rtworldshadows = false;
6358                 r_refdef.scene.rtdlight = false;
6359                 r_refdef.scene.rtdlightshadows = false;
6360                 r_refdef.lightmapintensity = 0;
6361         }
6362
6363         if (gamemode == GAME_NEHAHRA)
6364         {
6365                 if (gl_fogenable.integer)
6366                 {
6367                         r_refdef.oldgl_fogenable = true;
6368                         r_refdef.fog_density = gl_fogdensity.value;
6369                         r_refdef.fog_red = gl_fogred.value;
6370                         r_refdef.fog_green = gl_foggreen.value;
6371                         r_refdef.fog_blue = gl_fogblue.value;
6372                         r_refdef.fog_alpha = 1;
6373                         r_refdef.fog_start = 0;
6374                         r_refdef.fog_end = gl_skyclip.value;
6375                         r_refdef.fog_height = 1<<30;
6376                         r_refdef.fog_fadedepth = 128;
6377                 }
6378                 else if (r_refdef.oldgl_fogenable)
6379                 {
6380                         r_refdef.oldgl_fogenable = false;
6381                         r_refdef.fog_density = 0;
6382                         r_refdef.fog_red = 0;
6383                         r_refdef.fog_green = 0;
6384                         r_refdef.fog_blue = 0;
6385                         r_refdef.fog_alpha = 0;
6386                         r_refdef.fog_start = 0;
6387                         r_refdef.fog_end = 0;
6388                         r_refdef.fog_height = 1<<30;
6389                         r_refdef.fog_fadedepth = 128;
6390                 }
6391         }
6392
6393         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6394         r_refdef.fog_start = max(0, r_refdef.fog_start);
6395         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6396
6397         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6398
6399         if (r_refdef.fog_density && r_drawfog.integer)
6400         {
6401                 r_refdef.fogenabled = true;
6402                 // this is the point where the fog reaches 0.9986 alpha, which we
6403                 // consider a good enough cutoff point for the texture
6404                 // (0.9986 * 256 == 255.6)
6405                 if (r_fog_exp2.integer)
6406                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6407                 else
6408                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6409                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6410                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6411                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6412                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6413                         R_BuildFogHeightTexture();
6414                 // fog color was already set
6415                 // update the fog texture
6416                 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)
6417                         R_BuildFogTexture();
6418                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6419                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6420         }
6421         else
6422                 r_refdef.fogenabled = false;
6423
6424         switch(vid.renderpath)
6425         {
6426         case RENDERPATH_GL20:
6427         case RENDERPATH_D3D9:
6428         case RENDERPATH_D3D10:
6429         case RENDERPATH_D3D11:
6430         case RENDERPATH_SOFT:
6431         case RENDERPATH_GLES2:
6432                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6433                 {
6434                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6435                         {
6436                                 // build GLSL gamma texture
6437 #define RAMPWIDTH 256
6438                                 unsigned short ramp[RAMPWIDTH * 3];
6439                                 unsigned char rampbgr[RAMPWIDTH][4];
6440                                 int i;
6441
6442                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6443
6444                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6445                                 for(i = 0; i < RAMPWIDTH; ++i)
6446                                 {
6447                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6448                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6449                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6450                                         rampbgr[i][3] = 0;
6451                                 }
6452                                 if (r_texture_gammaramps)
6453                                 {
6454                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6455                                 }
6456                                 else
6457                                 {
6458                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6459                                 }
6460                         }
6461                 }
6462                 else
6463                 {
6464                         // remove GLSL gamma texture
6465                 }
6466                 break;
6467         case RENDERPATH_GL13:
6468         case RENDERPATH_GL11:
6469                 break;
6470         }
6471 }
6472
6473 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6474 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6475 /*
6476 ================
6477 R_SelectScene
6478 ================
6479 */
6480 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6481         if( scenetype != r_currentscenetype ) {
6482                 // store the old scenetype
6483                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6484                 r_currentscenetype = scenetype;
6485                 // move in the new scene
6486                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6487         }
6488 }
6489
6490 /*
6491 ================
6492 R_GetScenePointer
6493 ================
6494 */
6495 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6496 {
6497         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6498         if( scenetype == r_currentscenetype ) {
6499                 return &r_refdef.scene;
6500         } else {
6501                 return &r_scenes_store[ scenetype ];
6502         }
6503 }
6504
6505 /*
6506 ================
6507 R_RenderView
6508 ================
6509 */
6510 int dpsoftrast_test;
6511 void R_RenderView(void)
6512 {
6513         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6514
6515         dpsoftrast_test = r_test.integer;
6516
6517         if (r_timereport_active)
6518                 R_TimeReport("start");
6519         r_textureframe++; // used only by R_GetCurrentTexture
6520         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6521
6522         if(R_CompileShader_CheckStaticParms())
6523                 R_GLSL_Restart_f();
6524
6525         if (!r_drawentities.integer)
6526                 r_refdef.scene.numentities = 0;
6527
6528         R_AnimCache_ClearCache();
6529         R_FrameData_NewFrame();
6530
6531         /* adjust for stereo display */
6532         if(R_Stereo_Active())
6533         {
6534                 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);
6535                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6536         }
6537
6538         if (r_refdef.view.isoverlay)
6539         {
6540                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6541                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6542                 R_TimeReport("depthclear");
6543
6544                 r_refdef.view.showdebug = false;
6545
6546                 r_waterstate.enabled = false;
6547                 r_waterstate.numwaterplanes = 0;
6548
6549                 R_RenderScene();
6550
6551                 r_refdef.view.matrix = originalmatrix;
6552
6553                 CHECKGLERROR
6554                 return;
6555         }
6556
6557         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6558         {
6559                 r_refdef.view.matrix = originalmatrix;
6560                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6561         }
6562
6563         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6564
6565         R_RenderView_UpdateViewVectors();
6566
6567         R_Shadow_UpdateWorldLightSelection();
6568
6569         R_Bloom_StartFrame();
6570         R_Water_StartFrame();
6571
6572         CHECKGLERROR
6573         if (r_timereport_active)
6574                 R_TimeReport("viewsetup");
6575
6576         R_ResetViewRendering3D();
6577
6578         if (r_refdef.view.clear || r_refdef.fogenabled)
6579         {
6580                 R_ClearScreen(r_refdef.fogenabled);
6581                 if (r_timereport_active)
6582                         R_TimeReport("viewclear");
6583         }
6584         r_refdef.view.clear = true;
6585
6586         // this produces a bloom texture to be used in R_BlendView() later
6587         if (r_bloomstate.hdr)
6588         {
6589                 R_HDR_RenderBloomTexture();
6590                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6591                 r_textureframe++; // used only by R_GetCurrentTexture
6592         }
6593
6594         r_refdef.view.showdebug = true;
6595
6596         R_View_Update();
6597         if (r_timereport_active)
6598                 R_TimeReport("visibility");
6599
6600         r_waterstate.numwaterplanes = 0;
6601         if (r_waterstate.enabled)
6602                 R_RenderWaterPlanes();
6603
6604         R_RenderScene();
6605         r_waterstate.numwaterplanes = 0;
6606
6607         R_BlendView();
6608         if (r_timereport_active)
6609                 R_TimeReport("blendview");
6610
6611         GL_Scissor(0, 0, vid.width, vid.height);
6612         GL_ScissorTest(false);
6613
6614         r_refdef.view.matrix = originalmatrix;
6615
6616         CHECKGLERROR
6617 }
6618
6619 void R_RenderWaterPlanes(void)
6620 {
6621         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6622         {
6623                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6624                 if (r_timereport_active)
6625                         R_TimeReport("waterworld");
6626         }
6627
6628         // don't let sound skip if going slow
6629         if (r_refdef.scene.extraupdate)
6630                 S_ExtraUpdate ();
6631
6632         R_DrawModelsAddWaterPlanes();
6633         if (r_timereport_active)
6634                 R_TimeReport("watermodels");
6635
6636         if (r_waterstate.numwaterplanes)
6637         {
6638                 R_Water_ProcessPlanes();
6639                 if (r_timereport_active)
6640                         R_TimeReport("waterscenes");
6641         }
6642 }
6643
6644 extern void R_DrawLightningBeams (void);
6645 extern void VM_CL_AddPolygonsToMeshQueue (void);
6646 extern void R_DrawPortals (void);
6647 extern cvar_t cl_locs_show;
6648 static void R_DrawLocs(void);
6649 static void R_DrawEntityBBoxes(void);
6650 static void R_DrawModelDecals(void);
6651 extern void R_DrawModelShadows(void);
6652 extern void R_DrawModelShadowMaps(void);
6653 extern cvar_t cl_decals_newsystem;
6654 extern qboolean r_shadow_usingdeferredprepass;
6655 void R_RenderScene(void)
6656 {
6657         qboolean shadowmapping = false;
6658
6659         if (r_timereport_active)
6660                 R_TimeReport("beginscene");
6661
6662         r_refdef.stats.renders++;
6663
6664         R_UpdateFogColor();
6665
6666         // don't let sound skip if going slow
6667         if (r_refdef.scene.extraupdate)
6668                 S_ExtraUpdate ();
6669
6670         R_MeshQueue_BeginScene();
6671
6672         R_SkyStartFrame();
6673
6674         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);
6675
6676         if (r_timereport_active)
6677                 R_TimeReport("skystartframe");
6678
6679         if (cl.csqc_vidvars.drawworld)
6680         {
6681                 // don't let sound skip if going slow
6682                 if (r_refdef.scene.extraupdate)
6683                         S_ExtraUpdate ();
6684
6685                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6686                 {
6687                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6688                         if (r_timereport_active)
6689                                 R_TimeReport("worldsky");
6690                 }
6691
6692                 if (R_DrawBrushModelsSky() && r_timereport_active)
6693                         R_TimeReport("bmodelsky");
6694
6695                 if (skyrendermasked && skyrenderlater)
6696                 {
6697                         // we have to force off the water clipping plane while rendering sky
6698                         R_SetupView(false);
6699                         R_Sky();
6700                         R_SetupView(true);
6701                         if (r_timereport_active)
6702                                 R_TimeReport("sky");
6703                 }
6704         }
6705
6706         R_AnimCache_CacheVisibleEntities();
6707         if (r_timereport_active)
6708                 R_TimeReport("animation");
6709
6710         R_Shadow_PrepareLights();
6711         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6712                 R_Shadow_PrepareModelShadows();
6713         if (r_timereport_active)
6714                 R_TimeReport("preparelights");
6715
6716         if (R_Shadow_ShadowMappingEnabled())
6717                 shadowmapping = true;
6718
6719         if (r_shadow_usingdeferredprepass)
6720                 R_Shadow_DrawPrepass();
6721
6722         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6723         {
6724                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6725                 if (r_timereport_active)
6726                         R_TimeReport("worlddepth");
6727         }
6728         if (r_depthfirst.integer >= 2)
6729         {
6730                 R_DrawModelsDepth();
6731                 if (r_timereport_active)
6732                         R_TimeReport("modeldepth");
6733         }
6734
6735         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6736         {
6737                 R_DrawModelShadowMaps();
6738                 R_ResetViewRendering3D();
6739                 // don't let sound skip if going slow
6740                 if (r_refdef.scene.extraupdate)
6741                         S_ExtraUpdate ();
6742         }
6743
6744         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6745         {
6746                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6747                 if (r_timereport_active)
6748                         R_TimeReport("world");
6749         }
6750
6751         // don't let sound skip if going slow
6752         if (r_refdef.scene.extraupdate)
6753                 S_ExtraUpdate ();
6754
6755         R_DrawModels();
6756         if (r_timereport_active)
6757                 R_TimeReport("models");
6758
6759         // don't let sound skip if going slow
6760         if (r_refdef.scene.extraupdate)
6761                 S_ExtraUpdate ();
6762
6763         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6764         {
6765                 R_DrawModelShadows();
6766                 R_ResetViewRendering3D();
6767                 // don't let sound skip if going slow
6768                 if (r_refdef.scene.extraupdate)
6769                         S_ExtraUpdate ();
6770         }
6771
6772         if (!r_shadow_usingdeferredprepass)
6773         {
6774                 R_Shadow_DrawLights();
6775                 if (r_timereport_active)
6776                         R_TimeReport("rtlights");
6777         }
6778
6779         // don't let sound skip if going slow
6780         if (r_refdef.scene.extraupdate)
6781                 S_ExtraUpdate ();
6782
6783         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6784         {
6785                 R_DrawModelShadows();
6786                 R_ResetViewRendering3D();
6787                 // don't let sound skip if going slow
6788                 if (r_refdef.scene.extraupdate)
6789                         S_ExtraUpdate ();
6790         }
6791
6792         if (cl.csqc_vidvars.drawworld)
6793         {
6794                 if (cl_decals_newsystem.integer)
6795                 {
6796                         R_DrawModelDecals();
6797                         if (r_timereport_active)
6798                                 R_TimeReport("modeldecals");
6799                 }
6800                 else
6801                 {
6802                         R_DrawDecals();
6803                         if (r_timereport_active)
6804                                 R_TimeReport("decals");
6805                 }
6806
6807                 R_DrawParticles();
6808                 if (r_timereport_active)
6809                         R_TimeReport("particles");
6810
6811                 R_DrawExplosions();
6812                 if (r_timereport_active)
6813                         R_TimeReport("explosions");
6814
6815                 R_DrawLightningBeams();
6816                 if (r_timereport_active)
6817                         R_TimeReport("lightning");
6818         }
6819
6820         VM_CL_AddPolygonsToMeshQueue();
6821
6822         if (r_refdef.view.showdebug)
6823         {
6824                 if (cl_locs_show.integer)
6825                 {
6826                         R_DrawLocs();
6827                         if (r_timereport_active)
6828                                 R_TimeReport("showlocs");
6829                 }
6830
6831                 if (r_drawportals.integer)
6832                 {
6833                         R_DrawPortals();
6834                         if (r_timereport_active)
6835                                 R_TimeReport("portals");
6836                 }
6837
6838                 if (r_showbboxes.value > 0)
6839                 {
6840                         R_DrawEntityBBoxes();
6841                         if (r_timereport_active)
6842                                 R_TimeReport("bboxes");
6843                 }
6844         }
6845
6846         R_MeshQueue_RenderTransparent();
6847         if (r_timereport_active)
6848                 R_TimeReport("drawtrans");
6849
6850         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))
6851         {
6852                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6853                 if (r_timereport_active)
6854                         R_TimeReport("worlddebug");
6855                 R_DrawModelsDebug();
6856                 if (r_timereport_active)
6857                         R_TimeReport("modeldebug");
6858         }
6859
6860         if (cl.csqc_vidvars.drawworld)
6861         {
6862                 R_Shadow_DrawCoronas();
6863                 if (r_timereport_active)
6864                         R_TimeReport("coronas");
6865         }
6866
6867 #if 0
6868         {
6869                 GL_DepthTest(false);
6870                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6871                 GL_Color(1, 1, 1, 1);
6872                 qglBegin(GL_POLYGON);
6873                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6874                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6875                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6876                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6877                 qglEnd();
6878                 qglBegin(GL_POLYGON);
6879                 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]);
6880                 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]);
6881                 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]);
6882                 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]);
6883                 qglEnd();
6884                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6885         }
6886 #endif
6887
6888         // don't let sound skip if going slow
6889         if (r_refdef.scene.extraupdate)
6890                 S_ExtraUpdate ();
6891
6892         R_ResetViewRendering2D();
6893 }
6894
6895 static const unsigned short bboxelements[36] =
6896 {
6897         5, 1, 3, 5, 3, 7,
6898         6, 2, 0, 6, 0, 4,
6899         7, 3, 2, 7, 2, 6,
6900         4, 0, 1, 4, 1, 5,
6901         4, 5, 7, 4, 7, 6,
6902         1, 0, 2, 1, 2, 3,
6903 };
6904
6905 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6906 {
6907         int i;
6908         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6909
6910         RSurf_ActiveWorldEntity();
6911
6912         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6913         GL_DepthMask(false);
6914         GL_DepthRange(0, 1);
6915         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6916 //      R_Mesh_ResetTextureState();
6917
6918         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6919         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6920         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6921         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6922         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6923         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6924         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6925         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6926         R_FillColors(color4f, 8, cr, cg, cb, ca);
6927         if (r_refdef.fogenabled)
6928         {
6929                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6930                 {
6931                         f1 = RSurf_FogVertex(v);
6932                         f2 = 1 - f1;
6933                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6934                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6935                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6936                 }
6937         }
6938         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6939         R_Mesh_ResetTextureState();
6940         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6941         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6942 }
6943
6944 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6945 {
6946         int i;
6947         float color[4];
6948         prvm_edict_t *edict;
6949         prvm_prog_t *prog_save = prog;
6950
6951         // this function draws bounding boxes of server entities
6952         if (!sv.active)
6953                 return;
6954
6955         GL_CullFace(GL_NONE);
6956         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6957
6958         prog = 0;
6959         SV_VM_Begin();
6960         for (i = 0;i < numsurfaces;i++)
6961         {
6962                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6963                 switch ((int)edict->fields.server->solid)
6964                 {
6965                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6966                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6967                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6968                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6969                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6970                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6971                 }
6972                 color[3] *= r_showbboxes.value;
6973                 color[3] = bound(0, color[3], 1);
6974                 GL_DepthTest(!r_showdisabledepthtest.integer);
6975                 GL_CullFace(r_refdef.view.cullface_front);
6976                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6977         }
6978         SV_VM_End();
6979         prog = prog_save;
6980 }
6981
6982 static void R_DrawEntityBBoxes(void)
6983 {
6984         int i;
6985         prvm_edict_t *edict;
6986         vec3_t center;
6987         prvm_prog_t *prog_save = prog;
6988
6989         // this function draws bounding boxes of server entities
6990         if (!sv.active)
6991                 return;
6992
6993         prog = 0;
6994         SV_VM_Begin();
6995         for (i = 0;i < prog->num_edicts;i++)
6996         {
6997                 edict = PRVM_EDICT_NUM(i);
6998                 if (edict->priv.server->free)
6999                         continue;
7000                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7001                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7002                         continue;
7003                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7004                         continue;
7005                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7006                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7007         }
7008         SV_VM_End();
7009         prog = prog_save;
7010 }
7011
7012 static const int nomodelelement3i[24] =
7013 {
7014         5, 2, 0,
7015         5, 1, 2,
7016         5, 0, 3,
7017         5, 3, 1,
7018         0, 2, 4,
7019         2, 1, 4,
7020         3, 0, 4,
7021         1, 3, 4
7022 };
7023
7024 static const unsigned short nomodelelement3s[24] =
7025 {
7026         5, 2, 0,
7027         5, 1, 2,
7028         5, 0, 3,
7029         5, 3, 1,
7030         0, 2, 4,
7031         2, 1, 4,
7032         3, 0, 4,
7033         1, 3, 4
7034 };
7035
7036 static const float nomodelvertex3f[6*3] =
7037 {
7038         -16,   0,   0,
7039          16,   0,   0,
7040           0, -16,   0,
7041           0,  16,   0,
7042           0,   0, -16,
7043           0,   0,  16
7044 };
7045
7046 static const float nomodelcolor4f[6*4] =
7047 {
7048         0.0f, 0.0f, 0.5f, 1.0f,
7049         0.0f, 0.0f, 0.5f, 1.0f,
7050         0.0f, 0.5f, 0.0f, 1.0f,
7051         0.0f, 0.5f, 0.0f, 1.0f,
7052         0.5f, 0.0f, 0.0f, 1.0f,
7053         0.5f, 0.0f, 0.0f, 1.0f
7054 };
7055
7056 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7057 {
7058         int i;
7059         float f1, f2, *c;
7060         float color4f[6*4];
7061
7062         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);
7063
7064         // this is only called once per entity so numsurfaces is always 1, and
7065         // surfacelist is always {0}, so this code does not handle batches
7066
7067         if (rsurface.ent_flags & RENDER_ADDITIVE)
7068         {
7069                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7070                 GL_DepthMask(false);
7071         }
7072         else if (rsurface.colormod[3] < 1)
7073         {
7074                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7075                 GL_DepthMask(false);
7076         }
7077         else
7078         {
7079                 GL_BlendFunc(GL_ONE, GL_ZERO);
7080                 GL_DepthMask(true);
7081         }
7082         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7083         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7084         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7085         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7086         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7087         for (i = 0, c = color4f;i < 6;i++, c += 4)
7088         {
7089                 c[0] *= rsurface.colormod[0];
7090                 c[1] *= rsurface.colormod[1];
7091                 c[2] *= rsurface.colormod[2];
7092                 c[3] *= rsurface.colormod[3];
7093         }
7094         if (r_refdef.fogenabled)
7095         {
7096                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7097                 {
7098                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7099                         f2 = 1 - f1;
7100                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7101                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7102                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7103                 }
7104         }
7105 //      R_Mesh_ResetTextureState();
7106         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7107         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7108         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7109 }
7110
7111 void R_DrawNoModel(entity_render_t *ent)
7112 {
7113         vec3_t org;
7114         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7115         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7116                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7117         else
7118                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7119 }
7120
7121 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7122 {
7123         vec3_t right1, right2, diff, normal;
7124
7125         VectorSubtract (org2, org1, normal);
7126
7127         // calculate 'right' vector for start
7128         VectorSubtract (r_refdef.view.origin, org1, diff);
7129         CrossProduct (normal, diff, right1);
7130         VectorNormalize (right1);
7131
7132         // calculate 'right' vector for end
7133         VectorSubtract (r_refdef.view.origin, org2, diff);
7134         CrossProduct (normal, diff, right2);
7135         VectorNormalize (right2);
7136
7137         vert[ 0] = org1[0] + width * right1[0];
7138         vert[ 1] = org1[1] + width * right1[1];
7139         vert[ 2] = org1[2] + width * right1[2];
7140         vert[ 3] = org1[0] - width * right1[0];
7141         vert[ 4] = org1[1] - width * right1[1];
7142         vert[ 5] = org1[2] - width * right1[2];
7143         vert[ 6] = org2[0] - width * right2[0];
7144         vert[ 7] = org2[1] - width * right2[1];
7145         vert[ 8] = org2[2] - width * right2[2];
7146         vert[ 9] = org2[0] + width * right2[0];
7147         vert[10] = org2[1] + width * right2[1];
7148         vert[11] = org2[2] + width * right2[2];
7149 }
7150
7151 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)
7152 {
7153         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7154         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7155         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7156         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7157         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7158         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7159         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7160         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7161         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7162         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7163         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7164         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7165 }
7166
7167 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7168 {
7169         int i;
7170         float *vertex3f;
7171         float v[3];
7172         VectorSet(v, x, y, z);
7173         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7174                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7175                         break;
7176         if (i == mesh->numvertices)
7177         {
7178                 if (mesh->numvertices < mesh->maxvertices)
7179                 {
7180                         VectorCopy(v, vertex3f);
7181                         mesh->numvertices++;
7182                 }
7183                 return mesh->numvertices;
7184         }
7185         else
7186                 return i;
7187 }
7188
7189 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7190 {
7191         int i;
7192         int *e, element[3];
7193         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7194         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7195         e = mesh->element3i + mesh->numtriangles * 3;
7196         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7197         {
7198                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7199                 if (mesh->numtriangles < mesh->maxtriangles)
7200                 {
7201                         *e++ = element[0];
7202                         *e++ = element[1];
7203                         *e++ = element[2];
7204                         mesh->numtriangles++;
7205                 }
7206                 element[1] = element[2];
7207         }
7208 }
7209
7210 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7211 {
7212         int i;
7213         int *e, element[3];
7214         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7215         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7216         e = mesh->element3i + mesh->numtriangles * 3;
7217         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7218         {
7219                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7220                 if (mesh->numtriangles < mesh->maxtriangles)
7221                 {
7222                         *e++ = element[0];
7223                         *e++ = element[1];
7224                         *e++ = element[2];
7225                         mesh->numtriangles++;
7226                 }
7227                 element[1] = element[2];
7228         }
7229 }
7230
7231 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7232 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7233 {
7234         int planenum, planenum2;
7235         int w;
7236         int tempnumpoints;
7237         mplane_t *plane, *plane2;
7238         double maxdist;
7239         double temppoints[2][256*3];
7240         // figure out how large a bounding box we need to properly compute this brush
7241         maxdist = 0;
7242         for (w = 0;w < numplanes;w++)
7243                 maxdist = max(maxdist, fabs(planes[w].dist));
7244         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7245         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7246         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7247         {
7248                 w = 0;
7249                 tempnumpoints = 4;
7250                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7251                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7252                 {
7253                         if (planenum2 == planenum)
7254                                 continue;
7255                         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);
7256                         w = !w;
7257                 }
7258                 if (tempnumpoints < 3)
7259                         continue;
7260                 // generate elements forming a triangle fan for this polygon
7261                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7262         }
7263 }
7264
7265 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)
7266 {
7267         texturelayer_t *layer;
7268         layer = t->currentlayers + t->currentnumlayers++;
7269         layer->type = type;
7270         layer->depthmask = depthmask;
7271         layer->blendfunc1 = blendfunc1;
7272         layer->blendfunc2 = blendfunc2;
7273         layer->texture = texture;
7274         layer->texmatrix = *matrix;
7275         layer->color[0] = r;
7276         layer->color[1] = g;
7277         layer->color[2] = b;
7278         layer->color[3] = a;
7279 }
7280
7281 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7282 {
7283         if(parms[0] == 0 && parms[1] == 0)
7284                 return false;
7285         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7286                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7287                         return false;
7288         return true;
7289 }
7290
7291 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7292 {
7293         double index, f;
7294         index = parms[2] + r_refdef.scene.time * parms[3];
7295         index -= floor(index);
7296         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7297         {
7298         default:
7299         case Q3WAVEFUNC_NONE:
7300         case Q3WAVEFUNC_NOISE:
7301         case Q3WAVEFUNC_COUNT:
7302                 f = 0;
7303                 break;
7304         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7305         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7306         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7307         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7308         case Q3WAVEFUNC_TRIANGLE:
7309                 index *= 4;
7310                 f = index - floor(index);
7311                 if (index < 1)
7312                         f = f;
7313                 else if (index < 2)
7314                         f = 1 - f;
7315                 else if (index < 3)
7316                         f = -f;
7317                 else
7318                         f = -(1 - f);
7319                 break;
7320         }
7321         f = parms[0] + parms[1] * f;
7322         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7323                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7324         return (float) f;
7325 }
7326
7327 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7328 {
7329         int w, h, idx;
7330         float f;
7331         float tcmat[12];
7332         matrix4x4_t matrix, temp;
7333         switch(tcmod->tcmod)
7334         {
7335                 case Q3TCMOD_COUNT:
7336                 case Q3TCMOD_NONE:
7337                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7338                                 matrix = r_waterscrollmatrix;
7339                         else
7340                                 matrix = identitymatrix;
7341                         break;
7342                 case Q3TCMOD_ENTITYTRANSLATE:
7343                         // this is used in Q3 to allow the gamecode to control texcoord
7344                         // scrolling on the entity, which is not supported in darkplaces yet.
7345                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7346                         break;
7347                 case Q3TCMOD_ROTATE:
7348                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7349                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7350                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7351                         break;
7352                 case Q3TCMOD_SCALE:
7353                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7354                         break;
7355                 case Q3TCMOD_SCROLL:
7356                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7357                         break;
7358                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7359                         w = (int) tcmod->parms[0];
7360                         h = (int) tcmod->parms[1];
7361                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7362                         f = f - floor(f);
7363                         idx = (int) floor(f * w * h);
7364                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7365                         break;
7366                 case Q3TCMOD_STRETCH:
7367                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7368                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7369                         break;
7370                 case Q3TCMOD_TRANSFORM:
7371                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7372                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7373                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7374                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7375                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7376                         break;
7377                 case Q3TCMOD_TURBULENT:
7378                         // this is handled in the RSurf_PrepareVertices function
7379                         matrix = identitymatrix;
7380                         break;
7381         }
7382         temp = *texmatrix;
7383         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7384 }
7385
7386 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7387 {
7388         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7389         char name[MAX_QPATH];
7390         skinframe_t *skinframe;
7391         unsigned char pixels[296*194];
7392         strlcpy(cache->name, skinname, sizeof(cache->name));
7393         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7394         if (developer_loading.integer)
7395                 Con_Printf("loading %s\n", name);
7396         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7397         if (!skinframe || !skinframe->base)
7398         {
7399                 unsigned char *f;
7400                 fs_offset_t filesize;
7401                 skinframe = NULL;
7402                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7403                 if (f)
7404                 {
7405                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7406                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7407                         Mem_Free(f);
7408                 }
7409         }
7410         cache->skinframe = skinframe;
7411 }
7412
7413 texture_t *R_GetCurrentTexture(texture_t *t)
7414 {
7415         int i;
7416         const entity_render_t *ent = rsurface.entity;
7417         dp_model_t *model = ent->model;
7418         q3shaderinfo_layer_tcmod_t *tcmod;
7419
7420         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7421                 return t->currentframe;
7422         t->update_lastrenderframe = r_textureframe;
7423         t->update_lastrenderentity = (void *)ent;
7424
7425         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7426                 t->camera_entity = ent->entitynumber;
7427         else
7428                 t->camera_entity = 0;
7429
7430         // switch to an alternate material if this is a q1bsp animated material
7431         {
7432                 texture_t *texture = t;
7433                 int s = rsurface.ent_skinnum;
7434                 if ((unsigned int)s >= (unsigned int)model->numskins)
7435                         s = 0;
7436                 if (model->skinscenes)
7437                 {
7438                         if (model->skinscenes[s].framecount > 1)
7439                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7440                         else
7441                                 s = model->skinscenes[s].firstframe;
7442                 }
7443                 if (s > 0)
7444                         t = t + s * model->num_surfaces;
7445                 if (t->animated)
7446                 {
7447                         // use an alternate animation if the entity's frame is not 0,
7448                         // and only if the texture has an alternate animation
7449                         if (rsurface.ent_alttextures && t->anim_total[1])
7450                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7451                         else
7452                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7453                 }
7454                 texture->currentframe = t;
7455         }
7456
7457         // update currentskinframe to be a qw skin or animation frame
7458         if (rsurface.ent_qwskin >= 0)
7459         {
7460                 i = rsurface.ent_qwskin;
7461                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7462                 {
7463                         r_qwskincache_size = cl.maxclients;
7464                         if (r_qwskincache)
7465                                 Mem_Free(r_qwskincache);
7466                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7467                 }
7468                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7469                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7470                 t->currentskinframe = r_qwskincache[i].skinframe;
7471                 if (t->currentskinframe == NULL)
7472                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7473         }
7474         else if (t->numskinframes >= 2)
7475                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7476         if (t->backgroundnumskinframes >= 2)
7477                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7478
7479         t->currentmaterialflags = t->basematerialflags;
7480         t->currentalpha = rsurface.colormod[3];
7481         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7482                 t->currentalpha *= r_wateralpha.value;
7483         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7484                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7485         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7486                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7487         if (!(rsurface.ent_flags & RENDER_LIGHT))
7488                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7489         else if (FAKELIGHT_ENABLED)
7490         {
7491                         // no modellight if using fakelight for the map
7492         }
7493         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7494         {
7495                 // pick a model lighting mode
7496                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7497                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7498                 else
7499                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7500         }
7501         if (rsurface.ent_flags & RENDER_ADDITIVE)
7502                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7503         else if (t->currentalpha < 1)
7504                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7505         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7506                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7507         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7508                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7509         if (t->backgroundnumskinframes)
7510                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7511         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7512         {
7513                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7514                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7515         }
7516         else
7517                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7518         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7519                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7520
7521         // there is no tcmod
7522         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7523         {
7524                 t->currenttexmatrix = r_waterscrollmatrix;
7525                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7526         }
7527         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7528         {
7529                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7530                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7531         }
7532
7533         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7534                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7535         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7536                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7537
7538         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7539         if (t->currentskinframe->qpixels)
7540                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7541         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7542         if (!t->basetexture)
7543                 t->basetexture = r_texture_notexture;
7544         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7545         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7546         t->nmaptexture = t->currentskinframe->nmap;
7547         if (!t->nmaptexture)
7548                 t->nmaptexture = r_texture_blanknormalmap;
7549         t->glosstexture = r_texture_black;
7550         t->glowtexture = t->currentskinframe->glow;
7551         t->fogtexture = t->currentskinframe->fog;
7552         t->reflectmasktexture = t->currentskinframe->reflect;
7553         if (t->backgroundnumskinframes)
7554         {
7555                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7556                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7557                 t->backgroundglosstexture = r_texture_black;
7558                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7559                 if (!t->backgroundnmaptexture)
7560                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7561         }
7562         else
7563         {
7564                 t->backgroundbasetexture = r_texture_white;
7565                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7566                 t->backgroundglosstexture = r_texture_black;
7567                 t->backgroundglowtexture = NULL;
7568         }
7569         t->specularpower = r_shadow_glossexponent.value;
7570         // TODO: store reference values for these in the texture?
7571         t->specularscale = 0;
7572         if (r_shadow_gloss.integer > 0)
7573         {
7574                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7575                 {
7576                         if (r_shadow_glossintensity.value > 0)
7577                         {
7578                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7579                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7580                                 t->specularscale = r_shadow_glossintensity.value;
7581                         }
7582                 }
7583                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7584                 {
7585                         t->glosstexture = r_texture_white;
7586                         t->backgroundglosstexture = r_texture_white;
7587                         t->specularscale = r_shadow_gloss2intensity.value;
7588                         t->specularpower = r_shadow_gloss2exponent.value;
7589                 }
7590         }
7591         t->specularscale *= t->specularscalemod;
7592         t->specularpower *= t->specularpowermod;
7593
7594         // lightmaps mode looks bad with dlights using actual texturing, so turn
7595         // off the colormap and glossmap, but leave the normalmap on as it still
7596         // accurately represents the shading involved
7597         if (gl_lightmaps.integer)
7598         {
7599                 t->basetexture = r_texture_grey128;
7600                 t->pantstexture = r_texture_black;
7601                 t->shirttexture = r_texture_black;
7602                 t->nmaptexture = r_texture_blanknormalmap;
7603                 t->glosstexture = r_texture_black;
7604                 t->glowtexture = NULL;
7605                 t->fogtexture = NULL;
7606                 t->reflectmasktexture = NULL;
7607                 t->backgroundbasetexture = NULL;
7608                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7609                 t->backgroundglosstexture = r_texture_black;
7610                 t->backgroundglowtexture = NULL;
7611                 t->specularscale = 0;
7612                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7613         }
7614
7615         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7616         VectorClear(t->dlightcolor);
7617         t->currentnumlayers = 0;
7618         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7619         {
7620                 int blendfunc1, blendfunc2;
7621                 qboolean depthmask;
7622                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7623                 {
7624                         blendfunc1 = GL_SRC_ALPHA;
7625                         blendfunc2 = GL_ONE;
7626                 }
7627                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7628                 {
7629                         blendfunc1 = GL_SRC_ALPHA;
7630                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7631                 }
7632                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7633                 {
7634                         blendfunc1 = t->customblendfunc[0];
7635                         blendfunc2 = t->customblendfunc[1];
7636                 }
7637                 else
7638                 {
7639                         blendfunc1 = GL_ONE;
7640                         blendfunc2 = GL_ZERO;
7641                 }
7642                 // don't colormod evilblend textures
7643                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7644                         VectorSet(t->lightmapcolor, 1, 1, 1);
7645                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7646                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7647                 {
7648                         // fullbright is not affected by r_refdef.lightmapintensity
7649                         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]);
7650                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7651                                 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]);
7652                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7653                                 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]);
7654                 }
7655                 else
7656                 {
7657                         vec3_t ambientcolor;
7658                         float colorscale;
7659                         // set the color tint used for lights affecting this surface
7660                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7661                         colorscale = 2;
7662                         // q3bsp has no lightmap updates, so the lightstylevalue that
7663                         // would normally be baked into the lightmap must be
7664                         // applied to the color
7665                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7666                         if (model->type == mod_brushq3)
7667                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7668                         colorscale *= r_refdef.lightmapintensity;
7669                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7670                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7671                         // basic lit geometry
7672                         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]);
7673                         // add pants/shirt if needed
7674                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7675                                 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]);
7676                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7677                                 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]);
7678                         // now add ambient passes if needed
7679                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7680                         {
7681                                 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]);
7682                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7683                                         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]);
7684                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7685                                         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]);
7686                         }
7687                 }
7688                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7689                         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]);
7690                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7691                 {
7692                         // if this is opaque use alpha blend which will darken the earlier
7693                         // passes cheaply.
7694                         //
7695                         // if this is an alpha blended material, all the earlier passes
7696                         // were darkened by fog already, so we only need to add the fog
7697                         // color ontop through the fog mask texture
7698                         //
7699                         // if this is an additive blended material, all the earlier passes
7700                         // were darkened by fog already, and we should not add fog color
7701                         // (because the background was not darkened, there is no fog color
7702                         // that was lost behind it).
7703                         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]);
7704                 }
7705         }
7706
7707         return t->currentframe;
7708 }
7709
7710 rsurfacestate_t rsurface;
7711
7712 void RSurf_ActiveWorldEntity(void)
7713 {
7714         dp_model_t *model = r_refdef.scene.worldmodel;
7715         //if (rsurface.entity == r_refdef.scene.worldentity)
7716         //      return;
7717         rsurface.entity = r_refdef.scene.worldentity;
7718         rsurface.skeleton = NULL;
7719         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7720         rsurface.ent_skinnum = 0;
7721         rsurface.ent_qwskin = -1;
7722         rsurface.ent_shadertime = 0;
7723         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7724         rsurface.matrix = identitymatrix;
7725         rsurface.inversematrix = identitymatrix;
7726         rsurface.matrixscale = 1;
7727         rsurface.inversematrixscale = 1;
7728         R_EntityMatrix(&identitymatrix);
7729         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7730         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7731         rsurface.fograngerecip = r_refdef.fograngerecip;
7732         rsurface.fogheightfade = r_refdef.fogheightfade;
7733         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7734         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7735         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7736         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7737         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7738         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7739         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7740         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7741         rsurface.colormod[3] = 1;
7742         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);
7743         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7744         rsurface.frameblend[0].lerp = 1;
7745         rsurface.ent_alttextures = false;
7746         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7747         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7748         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7749         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7750         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7751         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7752         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7753         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7754         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7755         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7756         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7757         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7758         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7759         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7760         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7761         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7762         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7763         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7764         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7765         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7766         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7767         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7768         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7769         rsurface.modelelement3i = model->surfmesh.data_element3i;
7770         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7771         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7772         rsurface.modelelement3s = model->surfmesh.data_element3s;
7773         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7774         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7775         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7776         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7777         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7778         rsurface.modelsurfaces = model->data_surfaces;
7779         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7780         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7781         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7782         rsurface.modelgeneratedvertex = false;
7783         rsurface.batchgeneratedvertex = false;
7784         rsurface.batchfirstvertex = 0;
7785         rsurface.batchnumvertices = 0;
7786         rsurface.batchfirsttriangle = 0;
7787         rsurface.batchnumtriangles = 0;
7788         rsurface.batchvertex3f  = NULL;
7789         rsurface.batchvertex3f_vertexbuffer = NULL;
7790         rsurface.batchvertex3f_bufferoffset = 0;
7791         rsurface.batchsvector3f = NULL;
7792         rsurface.batchsvector3f_vertexbuffer = NULL;
7793         rsurface.batchsvector3f_bufferoffset = 0;
7794         rsurface.batchtvector3f = NULL;
7795         rsurface.batchtvector3f_vertexbuffer = NULL;
7796         rsurface.batchtvector3f_bufferoffset = 0;
7797         rsurface.batchnormal3f  = NULL;
7798         rsurface.batchnormal3f_vertexbuffer = NULL;
7799         rsurface.batchnormal3f_bufferoffset = 0;
7800         rsurface.batchlightmapcolor4f = NULL;
7801         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7802         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7803         rsurface.batchtexcoordtexture2f = NULL;
7804         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7805         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7806         rsurface.batchtexcoordlightmap2f = NULL;
7807         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7808         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7809         rsurface.batchvertexmesh = NULL;
7810         rsurface.batchvertexmeshbuffer = NULL;
7811         rsurface.batchvertex3fbuffer = NULL;
7812         rsurface.batchelement3i = NULL;
7813         rsurface.batchelement3i_indexbuffer = NULL;
7814         rsurface.batchelement3i_bufferoffset = 0;
7815         rsurface.batchelement3s = NULL;
7816         rsurface.batchelement3s_indexbuffer = NULL;
7817         rsurface.batchelement3s_bufferoffset = 0;
7818         rsurface.passcolor4f = NULL;
7819         rsurface.passcolor4f_vertexbuffer = NULL;
7820         rsurface.passcolor4f_bufferoffset = 0;
7821 }
7822
7823 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7824 {
7825         dp_model_t *model = ent->model;
7826         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7827         //      return;
7828         rsurface.entity = (entity_render_t *)ent;
7829         rsurface.skeleton = ent->skeleton;
7830         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7831         rsurface.ent_skinnum = ent->skinnum;
7832         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;
7833         rsurface.ent_shadertime = ent->shadertime;
7834         rsurface.ent_flags = ent->flags;
7835         rsurface.matrix = ent->matrix;
7836         rsurface.inversematrix = ent->inversematrix;
7837         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7838         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7839         R_EntityMatrix(&rsurface.matrix);
7840         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7841         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7842         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7843         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7844         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7845         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7846         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7847         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7848         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7849         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7850         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7851         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7852         rsurface.colormod[3] = ent->alpha;
7853         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7854         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7855         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7856         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7857         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7858         if (ent->model->brush.submodel && !prepass)
7859         {
7860                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7861                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7862         }
7863         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7864         {
7865                 if (ent->animcache_vertex3f)
7866                 {
7867                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7868                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7869                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7870                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7871                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7872                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7873                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7874                 }
7875                 else if (wanttangents)
7876                 {
7877                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7878                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7879                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
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, rsurface.modelsvector3f, rsurface.modeltvector3f);
7882                         rsurface.modelvertexmesh = NULL;
7883                         rsurface.modelvertexmeshbuffer = NULL;
7884                         rsurface.modelvertex3fbuffer = NULL;
7885                 }
7886                 else if (wantnormals)
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 = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7892                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7893                         rsurface.modelvertexmesh = NULL;
7894                         rsurface.modelvertexmeshbuffer = NULL;
7895                         rsurface.modelvertex3fbuffer = NULL;
7896                 }
7897                 else
7898                 {
7899                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7900                         rsurface.modelsvector3f = NULL;
7901                         rsurface.modeltvector3f = NULL;
7902                         rsurface.modelnormal3f = NULL;
7903                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7904                         rsurface.modelvertexmesh = NULL;
7905                         rsurface.modelvertexmeshbuffer = NULL;
7906                         rsurface.modelvertex3fbuffer = NULL;
7907                 }
7908                 rsurface.modelvertex3f_vertexbuffer = 0;
7909                 rsurface.modelvertex3f_bufferoffset = 0;
7910                 rsurface.modelsvector3f_vertexbuffer = 0;
7911                 rsurface.modelsvector3f_bufferoffset = 0;
7912                 rsurface.modeltvector3f_vertexbuffer = 0;
7913                 rsurface.modeltvector3f_bufferoffset = 0;
7914                 rsurface.modelnormal3f_vertexbuffer = 0;
7915                 rsurface.modelnormal3f_bufferoffset = 0;
7916                 rsurface.modelgeneratedvertex = true;
7917         }
7918         else
7919         {
7920                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7921                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7922                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7923                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7924                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7925                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7926                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7927                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7928                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7929                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7930                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7931                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7932                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7933                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7934                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7935                 rsurface.modelgeneratedvertex = false;
7936         }
7937         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7938         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7939         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7940         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7941         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7942         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7943         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7944         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7945         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7946         rsurface.modelelement3i = model->surfmesh.data_element3i;
7947         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7948         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7949         rsurface.modelelement3s = model->surfmesh.data_element3s;
7950         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7951         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7952         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7953         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7954         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7955         rsurface.modelsurfaces = model->data_surfaces;
7956         rsurface.batchgeneratedvertex = false;
7957         rsurface.batchfirstvertex = 0;
7958         rsurface.batchnumvertices = 0;
7959         rsurface.batchfirsttriangle = 0;
7960         rsurface.batchnumtriangles = 0;
7961         rsurface.batchvertex3f  = NULL;
7962         rsurface.batchvertex3f_vertexbuffer = NULL;
7963         rsurface.batchvertex3f_bufferoffset = 0;
7964         rsurface.batchsvector3f = NULL;
7965         rsurface.batchsvector3f_vertexbuffer = NULL;
7966         rsurface.batchsvector3f_bufferoffset = 0;
7967         rsurface.batchtvector3f = NULL;
7968         rsurface.batchtvector3f_vertexbuffer = NULL;
7969         rsurface.batchtvector3f_bufferoffset = 0;
7970         rsurface.batchnormal3f  = NULL;
7971         rsurface.batchnormal3f_vertexbuffer = NULL;
7972         rsurface.batchnormal3f_bufferoffset = 0;
7973         rsurface.batchlightmapcolor4f = NULL;
7974         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7975         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7976         rsurface.batchtexcoordtexture2f = NULL;
7977         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7978         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7979         rsurface.batchtexcoordlightmap2f = NULL;
7980         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7981         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7982         rsurface.batchvertexmesh = NULL;
7983         rsurface.batchvertexmeshbuffer = NULL;
7984         rsurface.batchvertex3fbuffer = NULL;
7985         rsurface.batchelement3i = NULL;
7986         rsurface.batchelement3i_indexbuffer = NULL;
7987         rsurface.batchelement3i_bufferoffset = 0;
7988         rsurface.batchelement3s = NULL;
7989         rsurface.batchelement3s_indexbuffer = NULL;
7990         rsurface.batchelement3s_bufferoffset = 0;
7991         rsurface.passcolor4f = NULL;
7992         rsurface.passcolor4f_vertexbuffer = NULL;
7993         rsurface.passcolor4f_bufferoffset = 0;
7994 }
7995
7996 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)
7997 {
7998         rsurface.entity = r_refdef.scene.worldentity;
7999         rsurface.skeleton = NULL;
8000         rsurface.ent_skinnum = 0;
8001         rsurface.ent_qwskin = -1;
8002         rsurface.ent_shadertime = shadertime;
8003         rsurface.ent_flags = entflags;
8004         rsurface.modelnumvertices = numvertices;
8005         rsurface.modelnumtriangles = numtriangles;
8006         rsurface.matrix = *matrix;
8007         rsurface.inversematrix = *inversematrix;
8008         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8009         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8010         R_EntityMatrix(&rsurface.matrix);
8011         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8012         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8013         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8014         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8015         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8016         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8017         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8018         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8019         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8020         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8021         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8022         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8023         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);
8024         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8025         rsurface.frameblend[0].lerp = 1;
8026         rsurface.ent_alttextures = false;
8027         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8028         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8029         if (wanttangents)
8030         {
8031                 rsurface.modelvertex3f = (float *)vertex3f;
8032                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8033                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8034                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8035         }
8036         else if (wantnormals)
8037         {
8038                 rsurface.modelvertex3f = (float *)vertex3f;
8039                 rsurface.modelsvector3f = NULL;
8040                 rsurface.modeltvector3f = NULL;
8041                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8042         }
8043         else
8044         {
8045                 rsurface.modelvertex3f = (float *)vertex3f;
8046                 rsurface.modelsvector3f = NULL;
8047                 rsurface.modeltvector3f = NULL;
8048                 rsurface.modelnormal3f = NULL;
8049         }
8050         rsurface.modelvertexmesh = NULL;
8051         rsurface.modelvertexmeshbuffer = NULL;
8052         rsurface.modelvertex3fbuffer = NULL;
8053         rsurface.modelvertex3f_vertexbuffer = 0;
8054         rsurface.modelvertex3f_bufferoffset = 0;
8055         rsurface.modelsvector3f_vertexbuffer = 0;
8056         rsurface.modelsvector3f_bufferoffset = 0;
8057         rsurface.modeltvector3f_vertexbuffer = 0;
8058         rsurface.modeltvector3f_bufferoffset = 0;
8059         rsurface.modelnormal3f_vertexbuffer = 0;
8060         rsurface.modelnormal3f_bufferoffset = 0;
8061         rsurface.modelgeneratedvertex = true;
8062         rsurface.modellightmapcolor4f  = (float *)color4f;
8063         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8064         rsurface.modellightmapcolor4f_bufferoffset = 0;
8065         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8066         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8067         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8068         rsurface.modeltexcoordlightmap2f  = NULL;
8069         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8070         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8071         rsurface.modelelement3i = (int *)element3i;
8072         rsurface.modelelement3i_indexbuffer = NULL;
8073         rsurface.modelelement3i_bufferoffset = 0;
8074         rsurface.modelelement3s = (unsigned short *)element3s;
8075         rsurface.modelelement3s_indexbuffer = NULL;
8076         rsurface.modelelement3s_bufferoffset = 0;
8077         rsurface.modellightmapoffsets = NULL;
8078         rsurface.modelsurfaces = NULL;
8079         rsurface.batchgeneratedvertex = false;
8080         rsurface.batchfirstvertex = 0;
8081         rsurface.batchnumvertices = 0;
8082         rsurface.batchfirsttriangle = 0;
8083         rsurface.batchnumtriangles = 0;
8084         rsurface.batchvertex3f  = NULL;
8085         rsurface.batchvertex3f_vertexbuffer = NULL;
8086         rsurface.batchvertex3f_bufferoffset = 0;
8087         rsurface.batchsvector3f = NULL;
8088         rsurface.batchsvector3f_vertexbuffer = NULL;
8089         rsurface.batchsvector3f_bufferoffset = 0;
8090         rsurface.batchtvector3f = NULL;
8091         rsurface.batchtvector3f_vertexbuffer = NULL;
8092         rsurface.batchtvector3f_bufferoffset = 0;
8093         rsurface.batchnormal3f  = NULL;
8094         rsurface.batchnormal3f_vertexbuffer = NULL;
8095         rsurface.batchnormal3f_bufferoffset = 0;
8096         rsurface.batchlightmapcolor4f = NULL;
8097         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8098         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8099         rsurface.batchtexcoordtexture2f = NULL;
8100         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8101         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8102         rsurface.batchtexcoordlightmap2f = NULL;
8103         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8104         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8105         rsurface.batchvertexmesh = NULL;
8106         rsurface.batchvertexmeshbuffer = NULL;
8107         rsurface.batchvertex3fbuffer = NULL;
8108         rsurface.batchelement3i = NULL;
8109         rsurface.batchelement3i_indexbuffer = NULL;
8110         rsurface.batchelement3i_bufferoffset = 0;
8111         rsurface.batchelement3s = NULL;
8112         rsurface.batchelement3s_indexbuffer = NULL;
8113         rsurface.batchelement3s_bufferoffset = 0;
8114         rsurface.passcolor4f = NULL;
8115         rsurface.passcolor4f_vertexbuffer = NULL;
8116         rsurface.passcolor4f_bufferoffset = 0;
8117
8118         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8119         {
8120                 if ((wantnormals || wanttangents) && !normal3f)
8121                 {
8122                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8123                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8124                 }
8125                 if (wanttangents && !svector3f)
8126                 {
8127                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8128                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8129                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8130                 }
8131         }
8132 }
8133
8134 float RSurf_FogPoint(const float *v)
8135 {
8136         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8137         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8138         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8139         float FogHeightFade = r_refdef.fogheightfade;
8140         float fogfrac;
8141         unsigned int fogmasktableindex;
8142         if (r_refdef.fogplaneviewabove)
8143                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8144         else
8145                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8146         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8147         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8148 }
8149
8150 float RSurf_FogVertex(const float *v)
8151 {
8152         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8153         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8154         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8155         float FogHeightFade = rsurface.fogheightfade;
8156         float fogfrac;
8157         unsigned int fogmasktableindex;
8158         if (r_refdef.fogplaneviewabove)
8159                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8160         else
8161                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8162         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8163         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8164 }
8165
8166 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8167 {
8168         int i;
8169         for (i = 0;i < numelements;i++)
8170                 outelement3i[i] = inelement3i[i] + adjust;
8171 }
8172
8173 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8174 extern cvar_t gl_vbo;
8175 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8176 {
8177         int deformindex;
8178         int firsttriangle;
8179         int numtriangles;
8180         int firstvertex;
8181         int endvertex;
8182         int numvertices;
8183         int surfacefirsttriangle;
8184         int surfacenumtriangles;
8185         int surfacefirstvertex;
8186         int surfaceendvertex;
8187         int surfacenumvertices;
8188         int batchnumvertices;
8189         int batchnumtriangles;
8190         int needsupdate;
8191         int i, j;
8192         qboolean gaps;
8193         qboolean dynamicvertex;
8194         float amplitude;
8195         float animpos;
8196         float scale;
8197         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8198         float waveparms[4];
8199         q3shaderinfo_deform_t *deform;
8200         const msurface_t *surface, *firstsurface;
8201         r_vertexmesh_t *vertexmesh;
8202         if (!texturenumsurfaces)
8203                 return;
8204         // find vertex range of this surface batch
8205         gaps = false;
8206         firstsurface = texturesurfacelist[0];
8207         firsttriangle = firstsurface->num_firsttriangle;
8208         batchnumvertices = 0;
8209         batchnumtriangles = 0;
8210         firstvertex = endvertex = firstsurface->num_firstvertex;
8211         for (i = 0;i < texturenumsurfaces;i++)
8212         {
8213                 surface = texturesurfacelist[i];
8214                 if (surface != firstsurface + i)
8215                         gaps = true;
8216                 surfacefirstvertex = surface->num_firstvertex;
8217                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8218                 surfacenumvertices = surface->num_vertices;
8219                 surfacenumtriangles = surface->num_triangles;
8220                 if (firstvertex > surfacefirstvertex)
8221                         firstvertex = surfacefirstvertex;
8222                 if (endvertex < surfaceendvertex)
8223                         endvertex = surfaceendvertex;
8224                 batchnumvertices += surfacenumvertices;
8225                 batchnumtriangles += surfacenumtriangles;
8226         }
8227
8228         // we now know the vertex range used, and if there are any gaps in it
8229         rsurface.batchfirstvertex = firstvertex;
8230         rsurface.batchnumvertices = endvertex - firstvertex;
8231         rsurface.batchfirsttriangle = firsttriangle;
8232         rsurface.batchnumtriangles = batchnumtriangles;
8233
8234         // this variable holds flags for which properties have been updated that
8235         // may require regenerating vertexmesh array...
8236         needsupdate = 0;
8237
8238         // check if any dynamic vertex processing must occur
8239         dynamicvertex = false;
8240
8241         // if there is a chance of animated vertex colors, it's a dynamic batch
8242         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8243         {
8244                 dynamicvertex = true;
8245                 batchneed |= BATCHNEED_NOGAPS;
8246                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8247         }
8248
8249         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8250         {
8251                 switch (deform->deform)
8252                 {
8253                 default:
8254                 case Q3DEFORM_PROJECTIONSHADOW:
8255                 case Q3DEFORM_TEXT0:
8256                 case Q3DEFORM_TEXT1:
8257                 case Q3DEFORM_TEXT2:
8258                 case Q3DEFORM_TEXT3:
8259                 case Q3DEFORM_TEXT4:
8260                 case Q3DEFORM_TEXT5:
8261                 case Q3DEFORM_TEXT6:
8262                 case Q3DEFORM_TEXT7:
8263                 case Q3DEFORM_NONE:
8264                         break;
8265                 case Q3DEFORM_AUTOSPRITE:
8266                         dynamicvertex = true;
8267                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8268                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8269                         break;
8270                 case Q3DEFORM_AUTOSPRITE2:
8271                         dynamicvertex = true;
8272                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8273                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8274                         break;
8275                 case Q3DEFORM_NORMAL:
8276                         dynamicvertex = true;
8277                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8278                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8279                         break;
8280                 case Q3DEFORM_WAVE:
8281                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8282                                 break; // if wavefunc is a nop, ignore this transform
8283                         dynamicvertex = true;
8284                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8285                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8286                         break;
8287                 case Q3DEFORM_BULGE:
8288                         dynamicvertex = true;
8289                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8290                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8291                         break;
8292                 case Q3DEFORM_MOVE:
8293                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8294                                 break; // if wavefunc is a nop, ignore this transform
8295                         dynamicvertex = true;
8296                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8297                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8298                         break;
8299                 }
8300         }
8301         switch(rsurface.texture->tcgen.tcgen)
8302         {
8303         default:
8304         case Q3TCGEN_TEXTURE:
8305                 break;
8306         case Q3TCGEN_LIGHTMAP:
8307                 dynamicvertex = true;
8308                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8309                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8310                 break;
8311         case Q3TCGEN_VECTOR:
8312                 dynamicvertex = true;
8313                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8314                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8315                 break;
8316         case Q3TCGEN_ENVIRONMENT:
8317                 dynamicvertex = true;
8318                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8319                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8320                 break;
8321         }
8322         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8323         {
8324                 dynamicvertex = true;
8325                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8326                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8327         }
8328
8329         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8330         {
8331                 dynamicvertex = true;
8332                 batchneed |= BATCHNEED_NOGAPS;
8333                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8334         }
8335
8336         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8337         {
8338                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8339                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8340                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8341                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8342                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8343                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8344                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8345         }
8346
8347         // when the model data has no vertex buffer (dynamic mesh), we need to
8348         // eliminate gaps
8349         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8350                 batchneed |= BATCHNEED_NOGAPS;
8351
8352         // if needsupdate, we have to do a dynamic vertex batch for sure
8353         if (needsupdate & batchneed)
8354                 dynamicvertex = true;
8355
8356         // see if we need to build vertexmesh from arrays
8357         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8358                 dynamicvertex = true;
8359
8360         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8361         // also some drivers strongly dislike firstvertex
8362         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8363                 dynamicvertex = true;
8364
8365         rsurface.batchvertex3f = rsurface.modelvertex3f;
8366         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8367         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8368         rsurface.batchsvector3f = rsurface.modelsvector3f;
8369         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8370         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8371         rsurface.batchtvector3f = rsurface.modeltvector3f;
8372         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8373         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8374         rsurface.batchnormal3f = rsurface.modelnormal3f;
8375         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8376         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8377         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8378         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8379         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8380         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8381         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8382         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8383         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8384         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8385         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8386         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8387         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8388         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8389         rsurface.batchelement3i = rsurface.modelelement3i;
8390         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8391         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8392         rsurface.batchelement3s = rsurface.modelelement3s;
8393         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8394         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8395
8396         // if any dynamic vertex processing has to occur in software, we copy the
8397         // entire surface list together before processing to rebase the vertices
8398         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8399         //
8400         // if any gaps exist and we do not have a static vertex buffer, we have to
8401         // copy the surface list together to avoid wasting upload bandwidth on the
8402         // vertices in the gaps.
8403         //
8404         // if gaps exist and we have a static vertex buffer, we still have to
8405         // combine the index buffer ranges into one dynamic index buffer.
8406         //
8407         // in all cases we end up with data that can be drawn in one call.
8408
8409         if (!dynamicvertex)
8410         {
8411                 // static vertex data, just set pointers...
8412                 rsurface.batchgeneratedvertex = false;
8413                 // if there are gaps, we want to build a combined index buffer,
8414                 // otherwise use the original static buffer with an appropriate offset
8415                 if (gaps)
8416                 {
8417                         // build a new triangle elements array for this batch
8418                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8419                         rsurface.batchfirsttriangle = 0;
8420                         numtriangles = 0;
8421                         for (i = 0;i < texturenumsurfaces;i++)
8422                         {
8423                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8424                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8425                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8426                                 numtriangles += surfacenumtriangles;
8427                         }
8428                         rsurface.batchelement3i_indexbuffer = NULL;
8429                         rsurface.batchelement3i_bufferoffset = 0;
8430                         rsurface.batchelement3s = NULL;
8431                         rsurface.batchelement3s_indexbuffer = NULL;
8432                         rsurface.batchelement3s_bufferoffset = 0;
8433                         if (endvertex <= 65536)
8434                         {
8435                                 // make a 16bit (unsigned short) index array if possible
8436                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8437                                 for (i = 0;i < numtriangles*3;i++)
8438                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8439                         }
8440                 }
8441                 return;
8442         }
8443
8444         // something needs software processing, do it for real...
8445         // we only directly handle separate array data in this case and then
8446         // generate interleaved data if needed...
8447         rsurface.batchgeneratedvertex = true;
8448
8449         // now copy the vertex data into a combined array and make an index array
8450         // (this is what Quake3 does all the time)
8451         //if (gaps || rsurface.batchfirstvertex)
8452         {
8453                 rsurface.batchvertex3fbuffer = NULL;
8454                 rsurface.batchvertexmesh = NULL;
8455                 rsurface.batchvertexmeshbuffer = NULL;
8456                 rsurface.batchvertex3f = NULL;
8457                 rsurface.batchvertex3f_vertexbuffer = NULL;
8458                 rsurface.batchvertex3f_bufferoffset = 0;
8459                 rsurface.batchsvector3f = NULL;
8460                 rsurface.batchsvector3f_vertexbuffer = NULL;
8461                 rsurface.batchsvector3f_bufferoffset = 0;
8462                 rsurface.batchtvector3f = NULL;
8463                 rsurface.batchtvector3f_vertexbuffer = NULL;
8464                 rsurface.batchtvector3f_bufferoffset = 0;
8465                 rsurface.batchnormal3f = NULL;
8466                 rsurface.batchnormal3f_vertexbuffer = NULL;
8467                 rsurface.batchnormal3f_bufferoffset = 0;
8468                 rsurface.batchlightmapcolor4f = NULL;
8469                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8470                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8471                 rsurface.batchtexcoordtexture2f = NULL;
8472                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8473                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8474                 rsurface.batchtexcoordlightmap2f = NULL;
8475                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8476                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8477                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8478                 rsurface.batchelement3i_indexbuffer = NULL;
8479                 rsurface.batchelement3i_bufferoffset = 0;
8480                 rsurface.batchelement3s = NULL;
8481                 rsurface.batchelement3s_indexbuffer = NULL;
8482                 rsurface.batchelement3s_bufferoffset = 0;
8483                 // we'll only be setting up certain arrays as needed
8484                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8485                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8486                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8487                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8488                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8489                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8490                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8491                 {
8492                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8493                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8494                 }
8495                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8496                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8497                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8498                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8499                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8500                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8501                 numvertices = 0;
8502                 numtriangles = 0;
8503                 for (i = 0;i < texturenumsurfaces;i++)
8504                 {
8505                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8506                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8507                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8508                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8509                         // copy only the data requested
8510                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8511                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8512                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8513                         {
8514                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8515                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8516                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8517                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8518                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8519                                 {
8520                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8521                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8522                                 }
8523                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8524                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8525                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8526                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8527                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8528                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8529                         }
8530                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8531                         numvertices += surfacenumvertices;
8532                         numtriangles += surfacenumtriangles;
8533                 }
8534
8535                 // generate a 16bit index array as well if possible
8536                 // (in general, dynamic batches fit)
8537                 if (numvertices <= 65536)
8538                 {
8539                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8540                         for (i = 0;i < numtriangles*3;i++)
8541                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8542                 }
8543
8544                 // since we've copied everything, the batch now starts at 0
8545                 rsurface.batchfirstvertex = 0;
8546                 rsurface.batchnumvertices = batchnumvertices;
8547                 rsurface.batchfirsttriangle = 0;
8548                 rsurface.batchnumtriangles = batchnumtriangles;
8549         }
8550
8551         // q1bsp surfaces rendered in vertex color mode have to have colors
8552         // calculated based on lightstyles
8553         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8554         {
8555                 // generate color arrays for the surfaces in this list
8556                 int c[4];
8557                 int scale;
8558                 int size3;
8559                 const int *offsets;
8560                 const unsigned char *lm;
8561                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8562                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8563                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8564                 numvertices = 0;
8565                 for (i = 0;i < texturenumsurfaces;i++)
8566                 {
8567                         surface = texturesurfacelist[i];
8568                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8569                         surfacenumvertices = surface->num_vertices;
8570                         if (surface->lightmapinfo->samples)
8571                         {
8572                                 for (j = 0;j < surfacenumvertices;j++)
8573                                 {
8574                                         lm = surface->lightmapinfo->samples + offsets[j];
8575                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8576                                         VectorScale(lm, scale, c);
8577                                         if (surface->lightmapinfo->styles[1] != 255)
8578                                         {
8579                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8580                                                 lm += size3;
8581                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8582                                                 VectorMA(c, scale, lm, c);
8583                                                 if (surface->lightmapinfo->styles[2] != 255)
8584                                                 {
8585                                                         lm += size3;
8586                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8587                                                         VectorMA(c, scale, lm, c);
8588                                                         if (surface->lightmapinfo->styles[3] != 255)
8589                                                         {
8590                                                                 lm += size3;
8591                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8592                                                                 VectorMA(c, scale, lm, c);
8593                                                         }
8594                                                 }
8595                                         }
8596                                         c[0] >>= 7;
8597                                         c[1] >>= 7;
8598                                         c[2] >>= 7;
8599                                         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);
8600                                         numvertices++;
8601                                 }
8602                         }
8603                         else
8604                         {
8605                                 for (j = 0;j < surfacenumvertices;j++)
8606                                 {
8607                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8608                                         numvertices++;
8609                                 }
8610                         }
8611                 }
8612         }
8613
8614         // if vertices are deformed (sprite flares and things in maps, possibly
8615         // water waves, bulges and other deformations), modify the copied vertices
8616         // in place
8617         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8618         {
8619                 switch (deform->deform)
8620                 {
8621                 default:
8622                 case Q3DEFORM_PROJECTIONSHADOW:
8623                 case Q3DEFORM_TEXT0:
8624                 case Q3DEFORM_TEXT1:
8625                 case Q3DEFORM_TEXT2:
8626                 case Q3DEFORM_TEXT3:
8627                 case Q3DEFORM_TEXT4:
8628                 case Q3DEFORM_TEXT5:
8629                 case Q3DEFORM_TEXT6:
8630                 case Q3DEFORM_TEXT7:
8631                 case Q3DEFORM_NONE:
8632                         break;
8633                 case Q3DEFORM_AUTOSPRITE:
8634                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8635                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8636                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8637                         VectorNormalize(newforward);
8638                         VectorNormalize(newright);
8639                         VectorNormalize(newup);
8640 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8641 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8642 //                      rsurface.batchvertex3f_bufferoffset = 0;
8643 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8644 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8645 //                      rsurface.batchsvector3f_bufferoffset = 0;
8646 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8647 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8648 //                      rsurface.batchtvector3f_bufferoffset = 0;
8649 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8650 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8651 //                      rsurface.batchnormal3f_bufferoffset = 0;
8652                         // a single autosprite surface can contain multiple sprites...
8653                         for (j = 0;j < batchnumvertices - 3;j += 4)
8654                         {
8655                                 VectorClear(center);
8656                                 for (i = 0;i < 4;i++)
8657                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8658                                 VectorScale(center, 0.25f, center);
8659                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8660                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8661                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8662                                 for (i = 0;i < 4;i++)
8663                                 {
8664                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8665                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8666                                 }
8667                         }
8668                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8669                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8670                         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);
8671                         break;
8672                 case Q3DEFORM_AUTOSPRITE2:
8673                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8674                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8675                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8676                         VectorNormalize(newforward);
8677                         VectorNormalize(newright);
8678                         VectorNormalize(newup);
8679 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8680 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8681 //                      rsurface.batchvertex3f_bufferoffset = 0;
8682                         {
8683                                 const float *v1, *v2;
8684                                 vec3_t start, end;
8685                                 float f, l;
8686                                 struct
8687                                 {
8688                                         float length2;
8689                                         const float *v1;
8690                                         const float *v2;
8691                                 }
8692                                 shortest[2];
8693                                 memset(shortest, 0, sizeof(shortest));
8694                                 // a single autosprite surface can contain multiple sprites...
8695                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8696                                 {
8697                                         VectorClear(center);
8698                                         for (i = 0;i < 4;i++)
8699                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8700                                         VectorScale(center, 0.25f, center);
8701                                         // find the two shortest edges, then use them to define the
8702                                         // axis vectors for rotating around the central axis
8703                                         for (i = 0;i < 6;i++)
8704                                         {
8705                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8706                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8707                                                 l = VectorDistance2(v1, v2);
8708                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8709                                                 if (v1[2] != v2[2])
8710                                                         l += (1.0f / 1024.0f);
8711                                                 if (shortest[0].length2 > l || i == 0)
8712                                                 {
8713                                                         shortest[1] = shortest[0];
8714                                                         shortest[0].length2 = l;
8715                                                         shortest[0].v1 = v1;
8716                                                         shortest[0].v2 = v2;
8717                                                 }
8718                                                 else if (shortest[1].length2 > l || i == 1)
8719                                                 {
8720                                                         shortest[1].length2 = l;
8721                                                         shortest[1].v1 = v1;
8722                                                         shortest[1].v2 = v2;
8723                                                 }
8724                                         }
8725                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8726                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8727                                         // this calculates the right vector from the shortest edge
8728                                         // and the up vector from the edge midpoints
8729                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8730                                         VectorNormalize(right);
8731                                         VectorSubtract(end, start, up);
8732                                         VectorNormalize(up);
8733                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8734                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8735                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8736                                         VectorNegate(forward, forward);
8737                                         VectorReflect(forward, 0, up, forward);
8738                                         VectorNormalize(forward);
8739                                         CrossProduct(up, forward, newright);
8740                                         VectorNormalize(newright);
8741                                         // rotate the quad around the up axis vector, this is made
8742                                         // especially easy by the fact we know the quad is flat,
8743                                         // so we only have to subtract the center position and
8744                                         // measure distance along the right vector, and then
8745                                         // multiply that by the newright vector and add back the
8746                                         // center position
8747                                         // we also need to subtract the old position to undo the
8748                                         // displacement from the center, which we do with a
8749                                         // DotProduct, the subtraction/addition of center is also
8750                                         // optimized into DotProducts here
8751                                         l = DotProduct(right, center);
8752                                         for (i = 0;i < 4;i++)
8753                                         {
8754                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8755                                                 f = DotProduct(right, v1) - l;
8756                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8757                                         }
8758                                 }
8759                         }
8760                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8761                         {
8762 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8763 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8764 //                              rsurface.batchnormal3f_bufferoffset = 0;
8765                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8766                         }
8767                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8768                         {
8769 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8770 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8771 //                              rsurface.batchsvector3f_bufferoffset = 0;
8772 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8773 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8774 //                              rsurface.batchtvector3f_bufferoffset = 0;
8775                                 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);
8776                         }
8777                         break;
8778                 case Q3DEFORM_NORMAL:
8779                         // deform the normals to make reflections wavey
8780                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8781                         rsurface.batchnormal3f_vertexbuffer = NULL;
8782                         rsurface.batchnormal3f_bufferoffset = 0;
8783                         for (j = 0;j < batchnumvertices;j++)
8784                         {
8785                                 float vertex[3];
8786                                 float *normal = rsurface.batchnormal3f + 3*j;
8787                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8788                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8789                                 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]);
8790                                 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]);
8791                                 VectorNormalize(normal);
8792                         }
8793                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8794                         {
8795 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8796 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8797 //                              rsurface.batchsvector3f_bufferoffset = 0;
8798 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8799 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8800 //                              rsurface.batchtvector3f_bufferoffset = 0;
8801                                 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);
8802                         }
8803                         break;
8804                 case Q3DEFORM_WAVE:
8805                         // deform vertex array to make wavey water and flags and such
8806                         waveparms[0] = deform->waveparms[0];
8807                         waveparms[1] = deform->waveparms[1];
8808                         waveparms[2] = deform->waveparms[2];
8809                         waveparms[3] = deform->waveparms[3];
8810                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8811                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8812                         // this is how a divisor of vertex influence on deformation
8813                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8814                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8815 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8816 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8817 //                      rsurface.batchvertex3f_bufferoffset = 0;
8818 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8819 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8820 //                      rsurface.batchnormal3f_bufferoffset = 0;
8821                         for (j = 0;j < batchnumvertices;j++)
8822                         {
8823                                 // if the wavefunc depends on time, evaluate it per-vertex
8824                                 if (waveparms[3])
8825                                 {
8826                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8827                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8828                                 }
8829                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8830                         }
8831                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8832                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8833                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8834                         {
8835 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8836 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8837 //                              rsurface.batchsvector3f_bufferoffset = 0;
8838 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8839 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8840 //                              rsurface.batchtvector3f_bufferoffset = 0;
8841                                 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);
8842                         }
8843                         break;
8844                 case Q3DEFORM_BULGE:
8845                         // deform vertex array to make the surface have moving bulges
8846 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8847 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8848 //                      rsurface.batchvertex3f_bufferoffset = 0;
8849 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8850 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8851 //                      rsurface.batchnormal3f_bufferoffset = 0;
8852                         for (j = 0;j < batchnumvertices;j++)
8853                         {
8854                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8855                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8856                         }
8857                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8858                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8859                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8860                         {
8861 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8862 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8863 //                              rsurface.batchsvector3f_bufferoffset = 0;
8864 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8865 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8866 //                              rsurface.batchtvector3f_bufferoffset = 0;
8867                                 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);
8868                         }
8869                         break;
8870                 case Q3DEFORM_MOVE:
8871                         // deform vertex array
8872                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8873                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8874                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8875                         VectorScale(deform->parms, scale, waveparms);
8876 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8877 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8878 //                      rsurface.batchvertex3f_bufferoffset = 0;
8879                         for (j = 0;j < batchnumvertices;j++)
8880                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8881                         break;
8882                 }
8883         }
8884
8885         // generate texcoords based on the chosen texcoord source
8886         switch(rsurface.texture->tcgen.tcgen)
8887         {
8888         default:
8889         case Q3TCGEN_TEXTURE:
8890                 break;
8891         case Q3TCGEN_LIGHTMAP:
8892 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8893 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8894 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8895                 if (rsurface.batchtexcoordlightmap2f)
8896                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8897                 break;
8898         case Q3TCGEN_VECTOR:
8899 //              rsurface.batchtexcoordtexture2f = 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                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8905                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8906                 }
8907                 break;
8908         case Q3TCGEN_ENVIRONMENT:
8909                 // make environment reflections using a spheremap
8910                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8911                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8912                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8913                 for (j = 0;j < batchnumvertices;j++)
8914                 {
8915                         // identical to Q3A's method, but executed in worldspace so
8916                         // carried models can be shiny too
8917
8918                         float viewer[3], d, reflected[3], worldreflected[3];
8919
8920                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8921                         // VectorNormalize(viewer);
8922
8923                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8924
8925                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8926                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8927                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8928                         // note: this is proportinal to viewer, so we can normalize later
8929
8930                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8931                         VectorNormalize(worldreflected);
8932
8933                         // note: this sphere map only uses world x and z!
8934                         // so positive and negative y will LOOK THE SAME.
8935                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8936                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8937                 }
8938                 break;
8939         }
8940         // the only tcmod that needs software vertex processing is turbulent, so
8941         // check for it here and apply the changes if needed
8942         // and we only support that as the first one
8943         // (handling a mixture of turbulent and other tcmods would be problematic
8944         //  without punting it entirely to a software path)
8945         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8946         {
8947                 amplitude = rsurface.texture->tcmods[0].parms[1];
8948                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8949 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8950 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8951 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8952                 for (j = 0;j < batchnumvertices;j++)
8953                 {
8954                         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);
8955                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8956                 }
8957         }
8958
8959         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8960         {
8961                 // convert the modified arrays to vertex structs
8962 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8963 //              rsurface.batchvertexmeshbuffer = NULL;
8964                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8965                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8966                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8967                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8968                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8969                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8970                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8971                 {
8972                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8973                         {
8974                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8975                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8976                         }
8977                 }
8978                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8979                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8980                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8981                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8982                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8983                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8984                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8985                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8986                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8987         }
8988 }
8989
8990 void RSurf_DrawBatch(void)
8991 {
8992         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8993         // through the pipeline, killing it earlier in the pipeline would have
8994         // per-surface overhead rather than per-batch overhead, so it's best to
8995         // reject it here, before it hits glDraw.
8996         if (rsurface.batchnumtriangles == 0)
8997                 return;
8998 #if 0
8999         // batch debugging code
9000         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9001         {
9002                 int i;
9003                 int j;
9004                 int c;
9005                 const int *e;
9006                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9007                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9008                 {
9009                         c = e[i];
9010                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9011                         {
9012                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9013                                 {
9014                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9015                                                 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);
9016                                         break;
9017                                 }
9018                         }
9019                 }
9020         }
9021 #endif
9022         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);
9023 }
9024
9025 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9026 {
9027         // pick the closest matching water plane
9028         int planeindex, vertexindex, bestplaneindex = -1;
9029         float d, bestd;
9030         vec3_t vert;
9031         const float *v;
9032         r_waterstate_waterplane_t *p;
9033         qboolean prepared = false;
9034         bestd = 0;
9035         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9036         {
9037                 if(p->camera_entity != rsurface.texture->camera_entity)
9038                         continue;
9039                 d = 0;
9040                 if(!prepared)
9041                 {
9042                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9043                         prepared = true;
9044                         if(rsurface.batchnumvertices == 0)
9045                                 break;
9046                 }
9047                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9048                 {
9049                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9050                         d += fabs(PlaneDiff(vert, &p->plane));
9051                 }
9052                 if (bestd > d || bestplaneindex < 0)
9053                 {
9054                         bestd = d;
9055                         bestplaneindex = planeindex;
9056                 }
9057         }
9058         return bestplaneindex;
9059         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9060         // this situation though, as it might be better to render single larger
9061         // batches with useless stuff (backface culled for example) than to
9062         // render multiple smaller batches
9063 }
9064
9065 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9066 {
9067         int i;
9068         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9069         rsurface.passcolor4f_vertexbuffer = 0;
9070         rsurface.passcolor4f_bufferoffset = 0;
9071         for (i = 0;i < rsurface.batchnumvertices;i++)
9072                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9073 }
9074
9075 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9076 {
9077         int i;
9078         float f;
9079         const float *v;
9080         const float *c;
9081         float *c2;
9082         if (rsurface.passcolor4f)
9083         {
9084                 // generate color arrays
9085                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9086                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9087                 rsurface.passcolor4f_vertexbuffer = 0;
9088                 rsurface.passcolor4f_bufferoffset = 0;
9089                 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)
9090                 {
9091                         f = RSurf_FogVertex(v);
9092                         c2[0] = c[0] * f;
9093                         c2[1] = c[1] * f;
9094                         c2[2] = c[2] * f;
9095                         c2[3] = c[3];
9096                 }
9097         }
9098         else
9099         {
9100                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9101                 rsurface.passcolor4f_vertexbuffer = 0;
9102                 rsurface.passcolor4f_bufferoffset = 0;
9103                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9104                 {
9105                         f = RSurf_FogVertex(v);
9106                         c2[0] = f;
9107                         c2[1] = f;
9108                         c2[2] = f;
9109                         c2[3] = 1;
9110                 }
9111         }
9112 }
9113
9114 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9115 {
9116         int i;
9117         float f;
9118         const float *v;
9119         const float *c;
9120         float *c2;
9121         if (!rsurface.passcolor4f)
9122                 return;
9123         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9124         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9125         rsurface.passcolor4f_vertexbuffer = 0;
9126         rsurface.passcolor4f_bufferoffset = 0;
9127         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)
9128         {
9129                 f = RSurf_FogVertex(v);
9130                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9131                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9132                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9133                 c2[3] = c[3];
9134         }
9135 }
9136
9137 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9138 {
9139         int i;
9140         const float *c;
9141         float *c2;
9142         if (!rsurface.passcolor4f)
9143                 return;
9144         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9145         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9146         rsurface.passcolor4f_vertexbuffer = 0;
9147         rsurface.passcolor4f_bufferoffset = 0;
9148         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9149         {
9150                 c2[0] = c[0] * r;
9151                 c2[1] = c[1] * g;
9152                 c2[2] = c[2] * b;
9153                 c2[3] = c[3] * a;
9154         }
9155 }
9156
9157 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9158 {
9159         int i;
9160         const float *c;
9161         float *c2;
9162         if (!rsurface.passcolor4f)
9163                 return;
9164         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9165         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9166         rsurface.passcolor4f_vertexbuffer = 0;
9167         rsurface.passcolor4f_bufferoffset = 0;
9168         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9169         {
9170                 c2[0] = c[0] + r_refdef.scene.ambient;
9171                 c2[1] = c[1] + r_refdef.scene.ambient;
9172                 c2[2] = c[2] + r_refdef.scene.ambient;
9173                 c2[3] = c[3];
9174         }
9175 }
9176
9177 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9178 {
9179         // TODO: optimize
9180         rsurface.passcolor4f = NULL;
9181         rsurface.passcolor4f_vertexbuffer = 0;
9182         rsurface.passcolor4f_bufferoffset = 0;
9183         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9184         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9185         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9186         GL_Color(r, g, b, a);
9187         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9188         RSurf_DrawBatch();
9189 }
9190
9191 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9192 {
9193         // TODO: optimize applyfog && applycolor case
9194         // just apply fog if necessary, and tint the fog color array if necessary
9195         rsurface.passcolor4f = NULL;
9196         rsurface.passcolor4f_vertexbuffer = 0;
9197         rsurface.passcolor4f_bufferoffset = 0;
9198         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9199         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9200         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9201         GL_Color(r, g, b, a);
9202         RSurf_DrawBatch();
9203 }
9204
9205 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9206 {
9207         // TODO: optimize
9208         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9209         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9210         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9211         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9212         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9213         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9214         GL_Color(r, g, b, a);
9215         RSurf_DrawBatch();
9216 }
9217
9218 static void RSurf_DrawBatch_GL11_ClampColor(void)
9219 {
9220         int i;
9221         const float *c1;
9222         float *c2;
9223         if (!rsurface.passcolor4f)
9224                 return;
9225         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9226         {
9227                 c2[0] = bound(0.0f, c1[0], 1.0f);
9228                 c2[1] = bound(0.0f, c1[1], 1.0f);
9229                 c2[2] = bound(0.0f, c1[2], 1.0f);
9230                 c2[3] = bound(0.0f, c1[3], 1.0f);
9231         }
9232 }
9233
9234 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9235 {
9236         int i;
9237         float f;
9238         const float *v;
9239         const float *n;
9240         float *c;
9241         //vec3_t eyedir;
9242
9243         // fake shading
9244         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9245         rsurface.passcolor4f_vertexbuffer = 0;
9246         rsurface.passcolor4f_bufferoffset = 0;
9247         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)
9248         {
9249                 f = -DotProduct(r_refdef.view.forward, n);
9250                 f = max(0, f);
9251                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9252                 f *= r_refdef.lightmapintensity;
9253                 Vector4Set(c, f, f, f, 1);
9254         }
9255 }
9256
9257 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9258 {
9259         RSurf_DrawBatch_GL11_ApplyFakeLight();
9260         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9261         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9262         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9263         GL_Color(r, g, b, a);
9264         RSurf_DrawBatch();
9265 }
9266
9267 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9268 {
9269         int i;
9270         float f;
9271         float alpha;
9272         const float *v;
9273         const float *n;
9274         float *c;
9275         vec3_t ambientcolor;
9276         vec3_t diffusecolor;
9277         vec3_t lightdir;
9278         // TODO: optimize
9279         // model lighting
9280         VectorCopy(rsurface.modellight_lightdir, lightdir);
9281         f = 0.5f * r_refdef.lightmapintensity;
9282         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9283         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9284         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9285         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9286         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9287         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9288         alpha = *a;
9289         if (VectorLength2(diffusecolor) > 0)
9290         {
9291                 // q3-style directional shading
9292                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9293                 rsurface.passcolor4f_vertexbuffer = 0;
9294                 rsurface.passcolor4f_bufferoffset = 0;
9295                 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)
9296                 {
9297                         if ((f = DotProduct(n, lightdir)) > 0)
9298                                 VectorMA(ambientcolor, f, diffusecolor, c);
9299                         else
9300                                 VectorCopy(ambientcolor, c);
9301                         c[3] = alpha;
9302                 }
9303                 *r = 1;
9304                 *g = 1;
9305                 *b = 1;
9306                 *a = 1;
9307                 *applycolor = false;
9308         }
9309         else
9310         {
9311                 *r = ambientcolor[0];
9312                 *g = ambientcolor[1];
9313                 *b = ambientcolor[2];
9314                 rsurface.passcolor4f = NULL;
9315                 rsurface.passcolor4f_vertexbuffer = 0;
9316                 rsurface.passcolor4f_bufferoffset = 0;
9317         }
9318 }
9319
9320 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9321 {
9322         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9323         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9324         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9325         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9326         GL_Color(r, g, b, a);
9327         RSurf_DrawBatch();
9328 }
9329
9330 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9331 {
9332         int i;
9333         float f;
9334         const float *v;
9335         float *c;
9336
9337         // fake shading
9338         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9339         rsurface.passcolor4f_vertexbuffer = 0;
9340         rsurface.passcolor4f_bufferoffset = 0;
9341
9342         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9343         {
9344                 f = 1 - RSurf_FogVertex(v);
9345                 c[0] = r;
9346                 c[1] = g;
9347                 c[2] = b;
9348                 c[3] = f * a;
9349         }
9350 }
9351
9352 void RSurf_SetupDepthAndCulling(void)
9353 {
9354         // submodels are biased to avoid z-fighting with world surfaces that they
9355         // may be exactly overlapping (avoids z-fighting artifacts on certain
9356         // doors and things in Quake maps)
9357         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9358         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9359         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9360         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9361 }
9362
9363 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9364 {
9365         // transparent sky would be ridiculous
9366         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9367                 return;
9368         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9369         skyrenderlater = true;
9370         RSurf_SetupDepthAndCulling();
9371         GL_DepthMask(true);
9372         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9373         // skymasking on them, and Quake3 never did sky masking (unlike
9374         // software Quake and software Quake2), so disable the sky masking
9375         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9376         // and skymasking also looks very bad when noclipping outside the
9377         // level, so don't use it then either.
9378         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9379         {
9380                 R_Mesh_ResetTextureState();
9381                 if (skyrendermasked)
9382                 {
9383                         R_SetupShader_DepthOrShadow();
9384                         // depth-only (masking)
9385                         GL_ColorMask(0,0,0,0);
9386                         // just to make sure that braindead drivers don't draw
9387                         // anything despite that colormask...
9388                         GL_BlendFunc(GL_ZERO, GL_ONE);
9389                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9390                         if (rsurface.batchvertex3fbuffer)
9391                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9392                         else
9393                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9394                 }
9395                 else
9396                 {
9397                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9398                         // fog sky
9399                         GL_BlendFunc(GL_ONE, GL_ZERO);
9400                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9401                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9402                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9403                 }
9404                 RSurf_DrawBatch();
9405                 if (skyrendermasked)
9406                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9407         }
9408         R_Mesh_ResetTextureState();
9409         GL_Color(1, 1, 1, 1);
9410 }
9411
9412 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9413 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9414 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9415 {
9416         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9417                 return;
9418         if (prepass)
9419         {
9420                 // render screenspace normalmap to texture
9421                 GL_DepthMask(true);
9422                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9423                 RSurf_DrawBatch();
9424                 return;
9425         }
9426
9427         // bind lightmap texture
9428
9429         // water/refraction/reflection/camera surfaces have to be handled specially
9430         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9431         {
9432                 int start, end, startplaneindex;
9433                 for (start = 0;start < texturenumsurfaces;start = end)
9434                 {
9435                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9436                         if(startplaneindex < 0)
9437                         {
9438                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9439                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9440                                 end = start + 1;
9441                                 continue;
9442                         }
9443                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9444                                 ;
9445                         // now that we have a batch using the same planeindex, render it
9446                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9447                         {
9448                                 // render water or distortion background
9449                                 GL_DepthMask(true);
9450                                 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));
9451                                 RSurf_DrawBatch();
9452                                 // blend surface on top
9453                                 GL_DepthMask(false);
9454                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9455                                 RSurf_DrawBatch();
9456                         }
9457                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9458                         {
9459                                 // render surface with reflection texture as input
9460                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9461                                 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));
9462                                 RSurf_DrawBatch();
9463                         }
9464                 }
9465                 return;
9466         }
9467
9468         // render surface batch normally
9469         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9470         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9471         RSurf_DrawBatch();
9472 }
9473
9474 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9475 {
9476         // OpenGL 1.3 path - anything not completely ancient
9477         qboolean applycolor;
9478         qboolean applyfog;
9479         int layerindex;
9480         const texturelayer_t *layer;
9481         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);
9482         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9483
9484         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9485         {
9486                 vec4_t layercolor;
9487                 int layertexrgbscale;
9488                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9489                 {
9490                         if (layerindex == 0)
9491                                 GL_AlphaTest(true);
9492                         else
9493                         {
9494                                 GL_AlphaTest(false);
9495                                 GL_DepthFunc(GL_EQUAL);
9496                         }
9497                 }
9498                 GL_DepthMask(layer->depthmask && writedepth);
9499                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9500                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9501                 {
9502                         layertexrgbscale = 4;
9503                         VectorScale(layer->color, 0.25f, layercolor);
9504                 }
9505                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9506                 {
9507                         layertexrgbscale = 2;
9508                         VectorScale(layer->color, 0.5f, layercolor);
9509                 }
9510                 else
9511                 {
9512                         layertexrgbscale = 1;
9513                         VectorScale(layer->color, 1.0f, layercolor);
9514                 }
9515                 layercolor[3] = layer->color[3];
9516                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9517                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9518                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9519                 switch (layer->type)
9520                 {
9521                 case TEXTURELAYERTYPE_LITTEXTURE:
9522                         // single-pass lightmapped texture with 2x rgbscale
9523                         R_Mesh_TexBind(0, r_texture_white);
9524                         R_Mesh_TexMatrix(0, NULL);
9525                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9526                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9527                         R_Mesh_TexBind(1, layer->texture);
9528                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9529                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9530                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9531                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9532                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9533                         else if (FAKELIGHT_ENABLED)
9534                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9535                         else if (rsurface.uselightmaptexture)
9536                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9537                         else
9538                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9539                         break;
9540                 case TEXTURELAYERTYPE_TEXTURE:
9541                         // singletexture unlit texture with transparency support
9542                         R_Mesh_TexBind(0, layer->texture);
9543                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9544                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9545                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9546                         R_Mesh_TexBind(1, 0);
9547                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9548                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9549                         break;
9550                 case TEXTURELAYERTYPE_FOG:
9551                         // singletexture fogging
9552                         if (layer->texture)
9553                         {
9554                                 R_Mesh_TexBind(0, layer->texture);
9555                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9556                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9557                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9558                         }
9559                         else
9560                         {
9561                                 R_Mesh_TexBind(0, 0);
9562                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9563                         }
9564                         R_Mesh_TexBind(1, 0);
9565                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9566                         // generate a color array for the fog pass
9567                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9568                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9569                         RSurf_DrawBatch();
9570                         break;
9571                 default:
9572                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9573                 }
9574         }
9575         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9576         {
9577                 GL_DepthFunc(GL_LEQUAL);
9578                 GL_AlphaTest(false);
9579         }
9580 }
9581
9582 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9583 {
9584         // OpenGL 1.1 - crusty old voodoo path
9585         qboolean applyfog;
9586         int layerindex;
9587         const texturelayer_t *layer;
9588         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);
9589         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9590
9591         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9592         {
9593                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9594                 {
9595                         if (layerindex == 0)
9596                                 GL_AlphaTest(true);
9597                         else
9598                         {
9599                                 GL_AlphaTest(false);
9600                                 GL_DepthFunc(GL_EQUAL);
9601                         }
9602                 }
9603                 GL_DepthMask(layer->depthmask && writedepth);
9604                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9605                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9606                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9607                 switch (layer->type)
9608                 {
9609                 case TEXTURELAYERTYPE_LITTEXTURE:
9610                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9611                         {
9612                                 // two-pass lit texture with 2x rgbscale
9613                                 // first the lightmap pass
9614                                 R_Mesh_TexBind(0, r_texture_white);
9615                                 R_Mesh_TexMatrix(0, NULL);
9616                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9617                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9618                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9619                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9620                                 else if (FAKELIGHT_ENABLED)
9621                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9622                                 else if (rsurface.uselightmaptexture)
9623                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9624                                 else
9625                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9626                                 // then apply the texture to it
9627                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9628                                 R_Mesh_TexBind(0, layer->texture);
9629                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9630                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9631                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9632                                 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);
9633                         }
9634                         else
9635                         {
9636                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9637                                 R_Mesh_TexBind(0, layer->texture);
9638                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9639                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9640                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9641                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9642                                         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);
9643                                 else
9644                                         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);
9645                         }
9646                         break;
9647                 case TEXTURELAYERTYPE_TEXTURE:
9648                         // singletexture unlit texture with transparency support
9649                         R_Mesh_TexBind(0, layer->texture);
9650                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9651                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9652                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9653                         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);
9654                         break;
9655                 case TEXTURELAYERTYPE_FOG:
9656                         // singletexture fogging
9657                         if (layer->texture)
9658                         {
9659                                 R_Mesh_TexBind(0, layer->texture);
9660                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9661                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9662                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9663                         }
9664                         else
9665                         {
9666                                 R_Mesh_TexBind(0, 0);
9667                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9668                         }
9669                         // generate a color array for the fog pass
9670                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9671                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9672                         RSurf_DrawBatch();
9673                         break;
9674                 default:
9675                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9676                 }
9677         }
9678         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9679         {
9680                 GL_DepthFunc(GL_LEQUAL);
9681                 GL_AlphaTest(false);
9682         }
9683 }
9684
9685 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9686 {
9687         int vi;
9688         int j;
9689         r_vertexgeneric_t *batchvertex;
9690         float c[4];
9691
9692 //      R_Mesh_ResetTextureState();
9693         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9694
9695         if(rsurface.texture && rsurface.texture->currentskinframe)
9696         {
9697                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9698                 c[3] *= rsurface.texture->currentalpha;
9699         }
9700         else
9701         {
9702                 c[0] = 1;
9703                 c[1] = 0;
9704                 c[2] = 1;
9705                 c[3] = 1;
9706         }
9707
9708         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9709         {
9710                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9711                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9712                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9713         }
9714
9715         // brighten it up (as texture value 127 means "unlit")
9716         c[0] *= 2 * r_refdef.view.colorscale;
9717         c[1] *= 2 * r_refdef.view.colorscale;
9718         c[2] *= 2 * r_refdef.view.colorscale;
9719
9720         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9721                 c[3] *= r_wateralpha.value;
9722
9723         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9724         {
9725                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9726                 GL_DepthMask(false);
9727         }
9728         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9729         {
9730                 GL_BlendFunc(GL_ONE, GL_ONE);
9731                 GL_DepthMask(false);
9732         }
9733         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9734         {
9735                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9736                 GL_DepthMask(false);
9737         }
9738         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9739         {
9740                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9741                 GL_DepthMask(false);
9742         }
9743         else
9744         {
9745                 GL_BlendFunc(GL_ONE, GL_ZERO);
9746                 GL_DepthMask(writedepth);
9747         }
9748
9749         if (r_showsurfaces.integer == 3)
9750         {
9751                 rsurface.passcolor4f = NULL;
9752
9753                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9754                 {
9755                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9756
9757                         rsurface.passcolor4f = NULL;
9758                         rsurface.passcolor4f_vertexbuffer = 0;
9759                         rsurface.passcolor4f_bufferoffset = 0;
9760                 }
9761                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9762                 {
9763                         qboolean applycolor = true;
9764                         float one = 1.0;
9765
9766                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9767
9768                         r_refdef.lightmapintensity = 1;
9769                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9770                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9771                 }
9772                 else if (FAKELIGHT_ENABLED)
9773                 {
9774                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9775
9776                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9777                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9778                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9779                 }
9780                 else
9781                 {
9782                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9783
9784                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9785                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9786                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9787                 }
9788
9789                 if(!rsurface.passcolor4f)
9790                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9791
9792                 RSurf_DrawBatch_GL11_ApplyAmbient();
9793                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9794                 if(r_refdef.fogenabled)
9795                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9796                 RSurf_DrawBatch_GL11_ClampColor();
9797
9798                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9799                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9800                 RSurf_DrawBatch();
9801         }
9802         else if (!r_refdef.view.showdebug)
9803         {
9804                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9805                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9806                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9807                 {
9808                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9809                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9810                 }
9811                 R_Mesh_PrepareVertices_Generic_Unlock();
9812                 RSurf_DrawBatch();
9813         }
9814         else if (r_showsurfaces.integer == 4)
9815         {
9816                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9817                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9818                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9819                 {
9820                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9821                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9822                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9823                 }
9824                 R_Mesh_PrepareVertices_Generic_Unlock();
9825                 RSurf_DrawBatch();
9826         }
9827         else if (r_showsurfaces.integer == 2)
9828         {
9829                 const int *e;
9830                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9831                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9832                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9833                 {
9834                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9835                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9836                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9837                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9838                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9839                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9840                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9841                 }
9842                 R_Mesh_PrepareVertices_Generic_Unlock();
9843                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9844         }
9845         else
9846         {
9847                 int texturesurfaceindex;
9848                 int k;
9849                 const msurface_t *surface;
9850                 float surfacecolor4f[4];
9851                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9852                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9853                 vi = 0;
9854                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9855                 {
9856                         surface = texturesurfacelist[texturesurfaceindex];
9857                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9858                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9859                         for (j = 0;j < surface->num_vertices;j++)
9860                         {
9861                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9862                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9863                                 vi++;
9864                         }
9865                 }
9866                 R_Mesh_PrepareVertices_Generic_Unlock();
9867                 RSurf_DrawBatch();
9868         }
9869 }
9870
9871 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9872 {
9873         CHECKGLERROR
9874         RSurf_SetupDepthAndCulling();
9875         if (r_showsurfaces.integer)
9876         {
9877                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9878                 return;
9879         }
9880         switch (vid.renderpath)
9881         {
9882         case RENDERPATH_GL20:
9883         case RENDERPATH_D3D9:
9884         case RENDERPATH_D3D10:
9885         case RENDERPATH_D3D11:
9886         case RENDERPATH_SOFT:
9887         case RENDERPATH_GLES2:
9888                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9889                 break;
9890         case RENDERPATH_GL13:
9891                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9892                 break;
9893         case RENDERPATH_GL11:
9894                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9895                 break;
9896         }
9897         CHECKGLERROR
9898 }
9899
9900 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9901 {
9902         CHECKGLERROR
9903         RSurf_SetupDepthAndCulling();
9904         if (r_showsurfaces.integer)
9905         {
9906                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9907                 return;
9908         }
9909         switch (vid.renderpath)
9910         {
9911         case RENDERPATH_GL20:
9912         case RENDERPATH_D3D9:
9913         case RENDERPATH_D3D10:
9914         case RENDERPATH_D3D11:
9915         case RENDERPATH_SOFT:
9916         case RENDERPATH_GLES2:
9917                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9918                 break;
9919         case RENDERPATH_GL13:
9920                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9921                 break;
9922         case RENDERPATH_GL11:
9923                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9924                 break;
9925         }
9926         CHECKGLERROR
9927 }
9928
9929 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9930 {
9931         int i, j;
9932         int texturenumsurfaces, endsurface;
9933         texture_t *texture;
9934         const msurface_t *surface;
9935 #define MAXBATCH_TRANSPARENTSURFACES 256
9936         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9937
9938         // if the model is static it doesn't matter what value we give for
9939         // wantnormals and wanttangents, so this logic uses only rules applicable
9940         // to a model, knowing that they are meaningless otherwise
9941         if (ent == r_refdef.scene.worldentity)
9942                 RSurf_ActiveWorldEntity();
9943         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9944                 RSurf_ActiveModelEntity(ent, false, false, false);
9945         else
9946         {
9947                 switch (vid.renderpath)
9948                 {
9949                 case RENDERPATH_GL20:
9950                 case RENDERPATH_D3D9:
9951                 case RENDERPATH_D3D10:
9952                 case RENDERPATH_D3D11:
9953                 case RENDERPATH_SOFT:
9954                 case RENDERPATH_GLES2:
9955                         RSurf_ActiveModelEntity(ent, true, true, false);
9956                         break;
9957                 case RENDERPATH_GL13:
9958                 case RENDERPATH_GL11:
9959                         RSurf_ActiveModelEntity(ent, true, false, false);
9960                         break;
9961                 }
9962         }
9963
9964         if (r_transparentdepthmasking.integer)
9965         {
9966                 qboolean setup = false;
9967                 for (i = 0;i < numsurfaces;i = j)
9968                 {
9969                         j = i + 1;
9970                         surface = rsurface.modelsurfaces + surfacelist[i];
9971                         texture = surface->texture;
9972                         rsurface.texture = R_GetCurrentTexture(texture);
9973                         rsurface.lightmaptexture = NULL;
9974                         rsurface.deluxemaptexture = NULL;
9975                         rsurface.uselightmaptexture = false;
9976                         // scan ahead until we find a different texture
9977                         endsurface = min(i + 1024, numsurfaces);
9978                         texturenumsurfaces = 0;
9979                         texturesurfacelist[texturenumsurfaces++] = surface;
9980                         for (;j < endsurface;j++)
9981                         {
9982                                 surface = rsurface.modelsurfaces + surfacelist[j];
9983                                 if (texture != surface->texture)
9984                                         break;
9985                                 texturesurfacelist[texturenumsurfaces++] = surface;
9986                         }
9987                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9988                                 continue;
9989                         // render the range of surfaces as depth
9990                         if (!setup)
9991                         {
9992                                 setup = true;
9993                                 GL_ColorMask(0,0,0,0);
9994                                 GL_Color(1,1,1,1);
9995                                 GL_DepthTest(true);
9996                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9997                                 GL_DepthMask(true);
9998 //                              R_Mesh_ResetTextureState();
9999                                 R_SetupShader_DepthOrShadow();
10000                         }
10001                         RSurf_SetupDepthAndCulling();
10002                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10003                         if (rsurface.batchvertex3fbuffer)
10004                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10005                         else
10006                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10007                         RSurf_DrawBatch();
10008                 }
10009                 if (setup)
10010                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10011         }
10012
10013         for (i = 0;i < numsurfaces;i = j)
10014         {
10015                 j = i + 1;
10016                 surface = rsurface.modelsurfaces + surfacelist[i];
10017                 texture = surface->texture;
10018                 rsurface.texture = R_GetCurrentTexture(texture);
10019                 // scan ahead until we find a different texture
10020                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10021                 texturenumsurfaces = 0;
10022                 texturesurfacelist[texturenumsurfaces++] = surface;
10023                 if(FAKELIGHT_ENABLED)
10024                 {
10025                         rsurface.lightmaptexture = NULL;
10026                         rsurface.deluxemaptexture = NULL;
10027                         rsurface.uselightmaptexture = false;
10028                         for (;j < endsurface;j++)
10029                         {
10030                                 surface = rsurface.modelsurfaces + surfacelist[j];
10031                                 if (texture != surface->texture)
10032                                         break;
10033                                 texturesurfacelist[texturenumsurfaces++] = surface;
10034                         }
10035                 }
10036                 else
10037                 {
10038                         rsurface.lightmaptexture = surface->lightmaptexture;
10039                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10040                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10041                         for (;j < endsurface;j++)
10042                         {
10043                                 surface = rsurface.modelsurfaces + surfacelist[j];
10044                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10045                                         break;
10046                                 texturesurfacelist[texturenumsurfaces++] = surface;
10047                         }
10048                 }
10049                 // render the range of surfaces
10050                 if (ent == r_refdef.scene.worldentity)
10051                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10052                 else
10053                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10054         }
10055         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10056 }
10057
10058 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10059 {
10060         // transparent surfaces get pushed off into the transparent queue
10061         int surfacelistindex;
10062         const msurface_t *surface;
10063         vec3_t tempcenter, center;
10064         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10065         {
10066                 surface = texturesurfacelist[surfacelistindex];
10067                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10068                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10069                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10070                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10071                 if (queueentity->transparent_offset) // transparent offset
10072                 {
10073                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10074                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10075                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10076                 }
10077                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10078         }
10079 }
10080
10081 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10082 {
10083         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10084                 return;
10085         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10086                 return;
10087         RSurf_SetupDepthAndCulling();
10088         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10089         if (rsurface.batchvertex3fbuffer)
10090                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10091         else
10092                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10093         RSurf_DrawBatch();
10094 }
10095
10096 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10097 {
10098         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10099         CHECKGLERROR
10100         if (depthonly)
10101                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10102         else if (prepass)
10103         {
10104                 if (!rsurface.texture->currentnumlayers)
10105                         return;
10106                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10107                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10108                 else
10109                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10110         }
10111         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10112                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10113         else if (!rsurface.texture->currentnumlayers)
10114                 return;
10115         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10116         {
10117                 // in the deferred case, transparent surfaces were queued during prepass
10118                 if (!r_shadow_usingdeferredprepass)
10119                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10120         }
10121         else
10122         {
10123                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10124                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10125         }
10126         CHECKGLERROR
10127 }
10128
10129 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10130 {
10131         int i, j;
10132         texture_t *texture;
10133         R_FrameData_SetMark();
10134         // break the surface list down into batches by texture and use of lightmapping
10135         for (i = 0;i < numsurfaces;i = j)
10136         {
10137                 j = i + 1;
10138                 // texture is the base texture pointer, rsurface.texture is the
10139                 // current frame/skin the texture is directing us to use (for example
10140                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10141                 // use skin 1 instead)
10142                 texture = surfacelist[i]->texture;
10143                 rsurface.texture = R_GetCurrentTexture(texture);
10144                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10145                 {
10146                         // if this texture is not the kind we want, skip ahead to the next one
10147                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10148                                 ;
10149                         continue;
10150                 }
10151                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10152                 {
10153                         rsurface.lightmaptexture = NULL;
10154                         rsurface.deluxemaptexture = NULL;
10155                         rsurface.uselightmaptexture = false;
10156                         // simply scan ahead until we find a different texture or lightmap state
10157                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10158                                 ;
10159                 }
10160                 else
10161                 {
10162                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10163                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10164                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10165                         // simply scan ahead until we find a different texture or lightmap state
10166                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10167                                 ;
10168                 }
10169                 // render the range of surfaces
10170                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10171         }
10172         R_FrameData_ReturnToMark();
10173 }
10174
10175 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10176 {
10177         CHECKGLERROR
10178         if (depthonly)
10179                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10180         else if (prepass)
10181         {
10182                 if (!rsurface.texture->currentnumlayers)
10183                         return;
10184                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10185                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10186                 else
10187                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10188         }
10189         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10190                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10191         else if (!rsurface.texture->currentnumlayers)
10192                 return;
10193         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10194         {
10195                 // in the deferred case, transparent surfaces were queued during prepass
10196                 if (!r_shadow_usingdeferredprepass)
10197                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10198         }
10199         else
10200         {
10201                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10202                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10203         }
10204         CHECKGLERROR
10205 }
10206
10207 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10208 {
10209         int i, j;
10210         texture_t *texture;
10211         R_FrameData_SetMark();
10212         // break the surface list down into batches by texture and use of lightmapping
10213         for (i = 0;i < numsurfaces;i = j)
10214         {
10215                 j = i + 1;
10216                 // texture is the base texture pointer, rsurface.texture is the
10217                 // current frame/skin the texture is directing us to use (for example
10218                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10219                 // use skin 1 instead)
10220                 texture = surfacelist[i]->texture;
10221                 rsurface.texture = R_GetCurrentTexture(texture);
10222                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10223                 {
10224                         // if this texture is not the kind we want, skip ahead to the next one
10225                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10226                                 ;
10227                         continue;
10228                 }
10229                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10230                 {
10231                         rsurface.lightmaptexture = NULL;
10232                         rsurface.deluxemaptexture = NULL;
10233                         rsurface.uselightmaptexture = false;
10234                         // simply scan ahead until we find a different texture or lightmap state
10235                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10236                                 ;
10237                 }
10238                 else
10239                 {
10240                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10241                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10242                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10243                         // simply scan ahead until we find a different texture or lightmap state
10244                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10245                                 ;
10246                 }
10247                 // render the range of surfaces
10248                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10249         }
10250         R_FrameData_ReturnToMark();
10251 }
10252
10253 float locboxvertex3f[6*4*3] =
10254 {
10255         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10256         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10257         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10258         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10259         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10260         1,0,0, 0,0,0, 0,1,0, 1,1,0
10261 };
10262
10263 unsigned short locboxelements[6*2*3] =
10264 {
10265          0, 1, 2, 0, 2, 3,
10266          4, 5, 6, 4, 6, 7,
10267          8, 9,10, 8,10,11,
10268         12,13,14, 12,14,15,
10269         16,17,18, 16,18,19,
10270         20,21,22, 20,22,23
10271 };
10272
10273 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10274 {
10275         int i, j;
10276         cl_locnode_t *loc = (cl_locnode_t *)ent;
10277         vec3_t mins, size;
10278         float vertex3f[6*4*3];
10279         CHECKGLERROR
10280         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10281         GL_DepthMask(false);
10282         GL_DepthRange(0, 1);
10283         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10284         GL_DepthTest(true);
10285         GL_CullFace(GL_NONE);
10286         R_EntityMatrix(&identitymatrix);
10287
10288 //      R_Mesh_ResetTextureState();
10289
10290         i = surfacelist[0];
10291         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10292                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10293                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10294                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10295
10296         if (VectorCompare(loc->mins, loc->maxs))
10297         {
10298                 VectorSet(size, 2, 2, 2);
10299                 VectorMA(loc->mins, -0.5f, size, mins);
10300         }
10301         else
10302         {
10303                 VectorCopy(loc->mins, mins);
10304                 VectorSubtract(loc->maxs, loc->mins, size);
10305         }
10306
10307         for (i = 0;i < 6*4*3;)
10308                 for (j = 0;j < 3;j++, i++)
10309                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10310
10311         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10312         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10313         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10314 }
10315
10316 void R_DrawLocs(void)
10317 {
10318         int index;
10319         cl_locnode_t *loc, *nearestloc;
10320         vec3_t center;
10321         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10322         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10323         {
10324                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10325                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10326         }
10327 }
10328
10329 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10330 {
10331         if (decalsystem->decals)
10332                 Mem_Free(decalsystem->decals);
10333         memset(decalsystem, 0, sizeof(*decalsystem));
10334 }
10335
10336 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)
10337 {
10338         tridecal_t *decal;
10339         tridecal_t *decals;
10340         int i;
10341
10342         // expand or initialize the system
10343         if (decalsystem->maxdecals <= decalsystem->numdecals)
10344         {
10345                 decalsystem_t old = *decalsystem;
10346                 qboolean useshortelements;
10347                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10348                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10349                 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)));
10350                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10351                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10352                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10353                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10354                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10355                 if (decalsystem->numdecals)
10356                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10357                 if (old.decals)
10358                         Mem_Free(old.decals);
10359                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10360                         decalsystem->element3i[i] = i;
10361                 if (useshortelements)
10362                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10363                                 decalsystem->element3s[i] = i;
10364         }
10365
10366         // grab a decal and search for another free slot for the next one
10367         decals = decalsystem->decals;
10368         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10369         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10370                 ;
10371         decalsystem->freedecal = i;
10372         if (decalsystem->numdecals <= i)
10373                 decalsystem->numdecals = i + 1;
10374
10375         // initialize the decal
10376         decal->lived = 0;
10377         decal->triangleindex = triangleindex;
10378         decal->surfaceindex = surfaceindex;
10379         decal->decalsequence = decalsequence;
10380         decal->color4f[0][0] = c0[0];
10381         decal->color4f[0][1] = c0[1];
10382         decal->color4f[0][2] = c0[2];
10383         decal->color4f[0][3] = 1;
10384         decal->color4f[1][0] = c1[0];
10385         decal->color4f[1][1] = c1[1];
10386         decal->color4f[1][2] = c1[2];
10387         decal->color4f[1][3] = 1;
10388         decal->color4f[2][0] = c2[0];
10389         decal->color4f[2][1] = c2[1];
10390         decal->color4f[2][2] = c2[2];
10391         decal->color4f[2][3] = 1;
10392         decal->vertex3f[0][0] = v0[0];
10393         decal->vertex3f[0][1] = v0[1];
10394         decal->vertex3f[0][2] = v0[2];
10395         decal->vertex3f[1][0] = v1[0];
10396         decal->vertex3f[1][1] = v1[1];
10397         decal->vertex3f[1][2] = v1[2];
10398         decal->vertex3f[2][0] = v2[0];
10399         decal->vertex3f[2][1] = v2[1];
10400         decal->vertex3f[2][2] = v2[2];
10401         decal->texcoord2f[0][0] = t0[0];
10402         decal->texcoord2f[0][1] = t0[1];
10403         decal->texcoord2f[1][0] = t1[0];
10404         decal->texcoord2f[1][1] = t1[1];
10405         decal->texcoord2f[2][0] = t2[0];
10406         decal->texcoord2f[2][1] = t2[1];
10407 }
10408
10409 extern cvar_t cl_decals_bias;
10410 extern cvar_t cl_decals_models;
10411 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10412 // baseparms, parms, temps
10413 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)
10414 {
10415         int cornerindex;
10416         int index;
10417         float v[9][3];
10418         const float *vertex3f;
10419         const float *normal3f;
10420         int numpoints;
10421         float points[2][9][3];
10422         float temp[3];
10423         float tc[9][2];
10424         float f;
10425         float c[9][4];
10426         const int *e;
10427
10428         e = rsurface.modelelement3i + 3*triangleindex;
10429
10430         vertex3f = rsurface.modelvertex3f;
10431         normal3f = rsurface.modelnormal3f;
10432
10433         if (normal3f)
10434         {
10435                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10436                 {
10437                         index = 3*e[cornerindex];
10438                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10439                 }
10440         }
10441         else
10442         {
10443                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10444                 {
10445                         index = 3*e[cornerindex];
10446                         VectorCopy(vertex3f + index, v[cornerindex]);
10447                 }
10448         }
10449
10450         // cull backfaces
10451         //TriangleNormal(v[0], v[1], v[2], normal);
10452         //if (DotProduct(normal, localnormal) < 0.0f)
10453         //      continue;
10454         // clip by each of the box planes formed from the projection matrix
10455         // if anything survives, we emit the decal
10456         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]);
10457         if (numpoints < 3)
10458                 return;
10459         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]);
10460         if (numpoints < 3)
10461                 return;
10462         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]);
10463         if (numpoints < 3)
10464                 return;
10465         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]);
10466         if (numpoints < 3)
10467                 return;
10468         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]);
10469         if (numpoints < 3)
10470                 return;
10471         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]);
10472         if (numpoints < 3)
10473                 return;
10474         // some part of the triangle survived, so we have to accept it...
10475         if (dynamic)
10476         {
10477                 // dynamic always uses the original triangle
10478                 numpoints = 3;
10479                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10480                 {
10481                         index = 3*e[cornerindex];
10482                         VectorCopy(vertex3f + index, v[cornerindex]);
10483                 }
10484         }
10485         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10486         {
10487                 // convert vertex positions to texcoords
10488                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10489                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10490                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10491                 // calculate distance fade from the projection origin
10492                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10493                 f = bound(0.0f, f, 1.0f);
10494                 c[cornerindex][0] = r * f;
10495                 c[cornerindex][1] = g * f;
10496                 c[cornerindex][2] = b * f;
10497                 c[cornerindex][3] = 1.0f;
10498                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10499         }
10500         if (dynamic)
10501                 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);
10502         else
10503                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10504                         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);
10505 }
10506 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)
10507 {
10508         matrix4x4_t projection;
10509         decalsystem_t *decalsystem;
10510         qboolean dynamic;
10511         dp_model_t *model;
10512         const msurface_t *surface;
10513         const msurface_t *surfaces;
10514         const int *surfacelist;
10515         const texture_t *texture;
10516         int numtriangles;
10517         int numsurfacelist;
10518         int surfacelistindex;
10519         int surfaceindex;
10520         int triangleindex;
10521         float localorigin[3];
10522         float localnormal[3];
10523         float localmins[3];
10524         float localmaxs[3];
10525         float localsize;
10526         //float normal[3];
10527         float planes[6][4];
10528         float angles[3];
10529         bih_t *bih;
10530         int bih_triangles_count;
10531         int bih_triangles[256];
10532         int bih_surfaces[256];
10533
10534         decalsystem = &ent->decalsystem;
10535         model = ent->model;
10536         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10537         {
10538                 R_DecalSystem_Reset(&ent->decalsystem);
10539                 return;
10540         }
10541
10542         if (!model->brush.data_leafs && !cl_decals_models.integer)
10543         {
10544                 if (decalsystem->model)
10545                         R_DecalSystem_Reset(decalsystem);
10546                 return;
10547         }
10548
10549         if (decalsystem->model != model)
10550                 R_DecalSystem_Reset(decalsystem);
10551         decalsystem->model = model;
10552
10553         RSurf_ActiveModelEntity(ent, true, false, false);
10554
10555         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10556         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10557         VectorNormalize(localnormal);
10558         localsize = worldsize*rsurface.inversematrixscale;
10559         localmins[0] = localorigin[0] - localsize;
10560         localmins[1] = localorigin[1] - localsize;
10561         localmins[2] = localorigin[2] - localsize;
10562         localmaxs[0] = localorigin[0] + localsize;
10563         localmaxs[1] = localorigin[1] + localsize;
10564         localmaxs[2] = localorigin[2] + localsize;
10565
10566         //VectorCopy(localnormal, planes[4]);
10567         //VectorVectors(planes[4], planes[2], planes[0]);
10568         AnglesFromVectors(angles, localnormal, NULL, false);
10569         AngleVectors(angles, planes[0], planes[2], planes[4]);
10570         VectorNegate(planes[0], planes[1]);
10571         VectorNegate(planes[2], planes[3]);
10572         VectorNegate(planes[4], planes[5]);
10573         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10574         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10575         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10576         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10577         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10578         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10579
10580 #if 1
10581 // works
10582 {
10583         matrix4x4_t forwardprojection;
10584         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10585         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10586 }
10587 #else
10588 // broken
10589 {
10590         float projectionvector[4][3];
10591         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10592         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10593         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10594         projectionvector[0][0] = planes[0][0] * ilocalsize;
10595         projectionvector[0][1] = planes[1][0] * ilocalsize;
10596         projectionvector[0][2] = planes[2][0] * ilocalsize;
10597         projectionvector[1][0] = planes[0][1] * ilocalsize;
10598         projectionvector[1][1] = planes[1][1] * ilocalsize;
10599         projectionvector[1][2] = planes[2][1] * ilocalsize;
10600         projectionvector[2][0] = planes[0][2] * ilocalsize;
10601         projectionvector[2][1] = planes[1][2] * ilocalsize;
10602         projectionvector[2][2] = planes[2][2] * ilocalsize;
10603         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10604         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10605         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10606         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10607 }
10608 #endif
10609
10610         dynamic = model->surfmesh.isanimated;
10611         numsurfacelist = model->nummodelsurfaces;
10612         surfacelist = model->sortedmodelsurfaces;
10613         surfaces = model->data_surfaces;
10614
10615         bih = NULL;
10616         bih_triangles_count = -1;
10617         if(!dynamic)
10618         {
10619                 if(model->render_bih.numleafs)
10620                         bih = &model->render_bih;
10621                 else if(model->collision_bih.numleafs)
10622                         bih = &model->collision_bih;
10623         }
10624         if(bih)
10625                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10626         if(bih_triangles_count == 0)
10627                 return;
10628         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10629                 return;
10630         if(bih_triangles_count > 0)
10631         {
10632                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10633                 {
10634                         surfaceindex = bih_surfaces[triangleindex];
10635                         surface = surfaces + surfaceindex;
10636                         texture = surface->texture;
10637                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10638                                 continue;
10639                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10640                                 continue;
10641                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10642                 }
10643         }
10644         else
10645         {
10646                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10647                 {
10648                         surfaceindex = surfacelist[surfacelistindex];
10649                         surface = surfaces + surfaceindex;
10650                         // check cull box first because it rejects more than any other check
10651                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10652                                 continue;
10653                         // skip transparent surfaces
10654                         texture = surface->texture;
10655                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10656                                 continue;
10657                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10658                                 continue;
10659                         numtriangles = surface->num_triangles;
10660                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10661                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10662                 }
10663         }
10664 }
10665
10666 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10667 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)
10668 {
10669         int renderentityindex;
10670         float worldmins[3];
10671         float worldmaxs[3];
10672         entity_render_t *ent;
10673
10674         if (!cl_decals_newsystem.integer)
10675                 return;
10676
10677         worldmins[0] = worldorigin[0] - worldsize;
10678         worldmins[1] = worldorigin[1] - worldsize;
10679         worldmins[2] = worldorigin[2] - worldsize;
10680         worldmaxs[0] = worldorigin[0] + worldsize;
10681         worldmaxs[1] = worldorigin[1] + worldsize;
10682         worldmaxs[2] = worldorigin[2] + worldsize;
10683
10684         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10685
10686         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10687         {
10688                 ent = r_refdef.scene.entities[renderentityindex];
10689                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10690                         continue;
10691
10692                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10693         }
10694 }
10695
10696 typedef struct r_decalsystem_splatqueue_s
10697 {
10698         vec3_t worldorigin;
10699         vec3_t worldnormal;
10700         float color[4];
10701         float tcrange[4];
10702         float worldsize;
10703         int decalsequence;
10704 }
10705 r_decalsystem_splatqueue_t;
10706
10707 int r_decalsystem_numqueued = 0;
10708 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10709
10710 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)
10711 {
10712         r_decalsystem_splatqueue_t *queue;
10713
10714         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10715                 return;
10716
10717         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10718         VectorCopy(worldorigin, queue->worldorigin);
10719         VectorCopy(worldnormal, queue->worldnormal);
10720         Vector4Set(queue->color, r, g, b, a);
10721         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10722         queue->worldsize = worldsize;
10723         queue->decalsequence = cl.decalsequence++;
10724 }
10725
10726 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10727 {
10728         int i;
10729         r_decalsystem_splatqueue_t *queue;
10730
10731         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10732                 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);
10733         r_decalsystem_numqueued = 0;
10734 }
10735
10736 extern cvar_t cl_decals_max;
10737 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10738 {
10739         int i;
10740         decalsystem_t *decalsystem = &ent->decalsystem;
10741         int numdecals;
10742         int killsequence;
10743         tridecal_t *decal;
10744         float frametime;
10745         float lifetime;
10746
10747         if (!decalsystem->numdecals)
10748                 return;
10749
10750         if (r_showsurfaces.integer)
10751                 return;
10752
10753         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10754         {
10755                 R_DecalSystem_Reset(decalsystem);
10756                 return;
10757         }
10758
10759         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10760         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10761
10762         if (decalsystem->lastupdatetime)
10763                 frametime = (cl.time - decalsystem->lastupdatetime);
10764         else
10765                 frametime = 0;
10766         decalsystem->lastupdatetime = cl.time;
10767         decal = decalsystem->decals;
10768         numdecals = decalsystem->numdecals;
10769
10770         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10771         {
10772                 if (decal->color4f[0][3])
10773                 {
10774                         decal->lived += frametime;
10775                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10776                         {
10777                                 memset(decal, 0, sizeof(*decal));
10778                                 if (decalsystem->freedecal > i)
10779                                         decalsystem->freedecal = i;
10780                         }
10781                 }
10782         }
10783         decal = decalsystem->decals;
10784         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10785                 numdecals--;
10786
10787         // collapse the array by shuffling the tail decals into the gaps
10788         for (;;)
10789         {
10790                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10791                         decalsystem->freedecal++;
10792                 if (decalsystem->freedecal == numdecals)
10793                         break;
10794                 decal[decalsystem->freedecal] = decal[--numdecals];
10795         }
10796
10797         decalsystem->numdecals = numdecals;
10798
10799         if (numdecals <= 0)
10800         {
10801                 // if there are no decals left, reset decalsystem
10802                 R_DecalSystem_Reset(decalsystem);
10803         }
10804 }
10805
10806 extern skinframe_t *decalskinframe;
10807 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10808 {
10809         int i;
10810         decalsystem_t *decalsystem = &ent->decalsystem;
10811         int numdecals;
10812         tridecal_t *decal;
10813         float faderate;
10814         float alpha;
10815         float *v3f;
10816         float *c4f;
10817         float *t2f;
10818         const int *e;
10819         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10820         int numtris = 0;
10821
10822         numdecals = decalsystem->numdecals;
10823         if (!numdecals)
10824                 return;
10825
10826         if (r_showsurfaces.integer)
10827                 return;
10828
10829         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10830         {
10831                 R_DecalSystem_Reset(decalsystem);
10832                 return;
10833         }
10834
10835         // if the model is static it doesn't matter what value we give for
10836         // wantnormals and wanttangents, so this logic uses only rules applicable
10837         // to a model, knowing that they are meaningless otherwise
10838         if (ent == r_refdef.scene.worldentity)
10839                 RSurf_ActiveWorldEntity();
10840         else
10841                 RSurf_ActiveModelEntity(ent, false, false, false);
10842
10843         decalsystem->lastupdatetime = cl.time;
10844         decal = decalsystem->decals;
10845
10846         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10847
10848         // update vertex positions for animated models
10849         v3f = decalsystem->vertex3f;
10850         c4f = decalsystem->color4f;
10851         t2f = decalsystem->texcoord2f;
10852         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10853         {
10854                 if (!decal->color4f[0][3])
10855                         continue;
10856
10857                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10858                         continue;
10859
10860                 // update color values for fading decals
10861                 if (decal->lived >= cl_decals_time.value)
10862                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10863                 else
10864                         alpha = 1.0f;
10865
10866                 c4f[ 0] = decal->color4f[0][0] * alpha;
10867                 c4f[ 1] = decal->color4f[0][1] * alpha;
10868                 c4f[ 2] = decal->color4f[0][2] * alpha;
10869                 c4f[ 3] = 1;
10870                 c4f[ 4] = decal->color4f[1][0] * alpha;
10871                 c4f[ 5] = decal->color4f[1][1] * alpha;
10872                 c4f[ 6] = decal->color4f[1][2] * alpha;
10873                 c4f[ 7] = 1;
10874                 c4f[ 8] = decal->color4f[2][0] * alpha;
10875                 c4f[ 9] = decal->color4f[2][1] * alpha;
10876                 c4f[10] = decal->color4f[2][2] * alpha;
10877                 c4f[11] = 1;
10878
10879                 t2f[0] = decal->texcoord2f[0][0];
10880                 t2f[1] = decal->texcoord2f[0][1];
10881                 t2f[2] = decal->texcoord2f[1][0];
10882                 t2f[3] = decal->texcoord2f[1][1];
10883                 t2f[4] = decal->texcoord2f[2][0];
10884                 t2f[5] = decal->texcoord2f[2][1];
10885
10886                 // update vertex positions for animated models
10887                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10888                 {
10889                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10890                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10891                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10892                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10893                 }
10894                 else
10895                 {
10896                         VectorCopy(decal->vertex3f[0], v3f);
10897                         VectorCopy(decal->vertex3f[1], v3f + 3);
10898                         VectorCopy(decal->vertex3f[2], v3f + 6);
10899                 }
10900
10901                 if (r_refdef.fogenabled)
10902                 {
10903                         alpha = RSurf_FogVertex(v3f);
10904                         VectorScale(c4f, alpha, c4f);
10905                         alpha = RSurf_FogVertex(v3f + 3);
10906                         VectorScale(c4f + 4, alpha, c4f + 4);
10907                         alpha = RSurf_FogVertex(v3f + 6);
10908                         VectorScale(c4f + 8, alpha, c4f + 8);
10909                 }
10910
10911                 v3f += 9;
10912                 c4f += 12;
10913                 t2f += 6;
10914                 numtris++;
10915         }
10916
10917         if (numtris > 0)
10918         {
10919                 r_refdef.stats.drawndecals += numtris;
10920
10921                 // now render the decals all at once
10922                 // (this assumes they all use one particle font texture!)
10923                 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);
10924 //              R_Mesh_ResetTextureState();
10925                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10926                 GL_DepthMask(false);
10927                 GL_DepthRange(0, 1);
10928                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10929                 GL_DepthTest(true);
10930                 GL_CullFace(GL_NONE);
10931                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10932                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10933                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10934         }
10935 }
10936
10937 static void R_DrawModelDecals(void)
10938 {
10939         int i, numdecals;
10940
10941         // fade faster when there are too many decals
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_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10947         for (i = 0;i < r_refdef.scene.numentities;i++)
10948                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10949                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10950
10951         R_DecalSystem_ApplySplatEntitiesQueue();
10952
10953         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10954         for (i = 0;i < r_refdef.scene.numentities;i++)
10955                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10956
10957         r_refdef.stats.totaldecals += numdecals;
10958
10959         if (r_showsurfaces.integer)
10960                 return;
10961
10962         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10963
10964         for (i = 0;i < r_refdef.scene.numentities;i++)
10965         {
10966                 if (!r_refdef.viewcache.entityvisible[i])
10967                         continue;
10968                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10969                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10970         }
10971 }
10972
10973 extern cvar_t mod_collision_bih;
10974 void R_DrawDebugModel(void)
10975 {
10976         entity_render_t *ent = rsurface.entity;
10977         int i, j, k, l, flagsmask;
10978         const msurface_t *surface;
10979         dp_model_t *model = ent->model;
10980         vec3_t v;
10981
10982         switch(vid.renderpath)
10983         {
10984         case RENDERPATH_GL11:
10985         case RENDERPATH_GL13:
10986         case RENDERPATH_GL20:
10987                 break;
10988         case RENDERPATH_D3D9:
10989                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10990                 return;
10991         case RENDERPATH_D3D10:
10992                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10993                 return;
10994         case RENDERPATH_D3D11:
10995                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10996                 return;
10997         case RENDERPATH_SOFT:
10998                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10999                 return;
11000         case RENDERPATH_GLES2:
11001                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11002                 return;
11003         }
11004
11005         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11006
11007 //      R_Mesh_ResetTextureState();
11008         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11009         GL_DepthRange(0, 1);
11010         GL_DepthTest(!r_showdisabledepthtest.integer);
11011         GL_DepthMask(false);
11012         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11013
11014         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11015         {
11016                 int triangleindex;
11017                 int bihleafindex;
11018                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11019                 const q3mbrush_t *brush;
11020                 const bih_t *bih = &model->collision_bih;
11021                 const bih_leaf_t *bihleaf;
11022                 float vertex3f[3][3];
11023                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11024                 cullbox = false;
11025                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11026                 {
11027                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11028                                 continue;
11029                         switch (bihleaf->type)
11030                         {
11031                         case BIH_BRUSH:
11032                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11033                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11034                                 {
11035                                         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);
11036                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11037                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11038                                 }
11039                                 break;
11040                         case BIH_COLLISIONTRIANGLE:
11041                                 triangleindex = bihleaf->itemindex;
11042                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11043                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11044                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11045                                 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);
11046                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11047                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11048                                 break;
11049                         case BIH_RENDERTRIANGLE:
11050                                 triangleindex = bihleaf->itemindex;
11051                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11052                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11053                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11054                                 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);
11055                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11056                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11057                                 break;
11058                         }
11059                 }
11060         }
11061
11062         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11063
11064         if (r_showtris.integer || (r_shownormals.value != 0))
11065         {
11066                 if (r_showdisabledepthtest.integer)
11067                 {
11068                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11069                         GL_DepthMask(false);
11070                 }
11071                 else
11072                 {
11073                         GL_BlendFunc(GL_ONE, GL_ZERO);
11074                         GL_DepthMask(true);
11075                 }
11076                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11077                 {
11078                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11079                                 continue;
11080                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11081                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11082                         {
11083                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11084                                 if (r_showtris.value > 0)
11085                                 {
11086                                         if (!rsurface.texture->currentlayers->depthmask)
11087                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11088                                         else if (ent == r_refdef.scene.worldentity)
11089                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11090                                         else
11091                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11092                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11093                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11094                                         RSurf_DrawBatch();
11095                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11096                                         CHECKGLERROR
11097                                 }
11098                                 if (r_shownormals.value < 0)
11099                                 {
11100                                         qglBegin(GL_LINES);
11101                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11102                                         {
11103                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11104                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11105                                                 qglVertex3f(v[0], v[1], v[2]);
11106                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11107                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11108                                                 qglVertex3f(v[0], v[1], v[2]);
11109                                         }
11110                                         qglEnd();
11111                                         CHECKGLERROR
11112                                 }
11113                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11114                                 {
11115                                         qglBegin(GL_LINES);
11116                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11117                                         {
11118                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11119                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11120                                                 qglVertex3f(v[0], v[1], v[2]);
11121                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11122                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11123                                                 qglVertex3f(v[0], v[1], v[2]);
11124                                         }
11125                                         qglEnd();
11126                                         CHECKGLERROR
11127                                         qglBegin(GL_LINES);
11128                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11129                                         {
11130                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11131                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11132                                                 qglVertex3f(v[0], v[1], v[2]);
11133                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11134                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11135                                                 qglVertex3f(v[0], v[1], v[2]);
11136                                         }
11137                                         qglEnd();
11138                                         CHECKGLERROR
11139                                         qglBegin(GL_LINES);
11140                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11141                                         {
11142                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11143                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11144                                                 qglVertex3f(v[0], v[1], v[2]);
11145                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11146                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11147                                                 qglVertex3f(v[0], v[1], v[2]);
11148                                         }
11149                                         qglEnd();
11150                                         CHECKGLERROR
11151                                 }
11152                         }
11153                 }
11154                 rsurface.texture = NULL;
11155         }
11156 }
11157
11158 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11159 int r_maxsurfacelist = 0;
11160 const msurface_t **r_surfacelist = NULL;
11161 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11162 {
11163         int i, j, endj, flagsmask;
11164         dp_model_t *model = r_refdef.scene.worldmodel;
11165         msurface_t *surfaces;
11166         unsigned char *update;
11167         int numsurfacelist = 0;
11168         if (model == NULL)
11169                 return;
11170
11171         if (r_maxsurfacelist < model->num_surfaces)
11172         {
11173                 r_maxsurfacelist = model->num_surfaces;
11174                 if (r_surfacelist)
11175                         Mem_Free((msurface_t**)r_surfacelist);
11176                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11177         }
11178
11179         RSurf_ActiveWorldEntity();
11180
11181         surfaces = model->data_surfaces;
11182         update = model->brushq1.lightmapupdateflags;
11183
11184         // update light styles on this submodel
11185         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11186         {
11187                 model_brush_lightstyleinfo_t *style;
11188                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11189                 {
11190                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11191                         {
11192                                 int *list = style->surfacelist;
11193                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11194                                 for (j = 0;j < style->numsurfaces;j++)
11195                                         update[list[j]] = true;
11196                         }
11197                 }
11198         }
11199
11200         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11201
11202         if (debug)
11203         {
11204                 R_DrawDebugModel();
11205                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11206                 return;
11207         }
11208
11209         rsurface.lightmaptexture = NULL;
11210         rsurface.deluxemaptexture = NULL;
11211         rsurface.uselightmaptexture = false;
11212         rsurface.texture = NULL;
11213         rsurface.rtlight = NULL;
11214         numsurfacelist = 0;
11215         // add visible surfaces to draw list
11216         for (i = 0;i < model->nummodelsurfaces;i++)
11217         {
11218                 j = model->sortedmodelsurfaces[i];
11219                 if (r_refdef.viewcache.world_surfacevisible[j])
11220                         r_surfacelist[numsurfacelist++] = surfaces + j;
11221         }
11222         // update lightmaps if needed
11223         if (model->brushq1.firstrender)
11224         {
11225                 model->brushq1.firstrender = false;
11226                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11227                         if (update[j])
11228                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11229         }
11230         else if (update)
11231         {
11232                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11233                         if (r_refdef.viewcache.world_surfacevisible[j])
11234                                 if (update[j])
11235                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11236         }
11237         // don't do anything if there were no surfaces
11238         if (!numsurfacelist)
11239         {
11240                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11241                 return;
11242         }
11243         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11244
11245         // add to stats if desired
11246         if (r_speeds.integer && !skysurfaces && !depthonly)
11247         {
11248                 r_refdef.stats.world_surfaces += numsurfacelist;
11249                 for (j = 0;j < numsurfacelist;j++)
11250                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11251         }
11252
11253         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11254 }
11255
11256 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11257 {
11258         int i, j, endj, flagsmask;
11259         dp_model_t *model = ent->model;
11260         msurface_t *surfaces;
11261         unsigned char *update;
11262         int numsurfacelist = 0;
11263         if (model == NULL)
11264                 return;
11265
11266         if (r_maxsurfacelist < model->num_surfaces)
11267         {
11268                 r_maxsurfacelist = model->num_surfaces;
11269                 if (r_surfacelist)
11270                         Mem_Free((msurface_t **)r_surfacelist);
11271                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11272         }
11273
11274         // if the model is static it doesn't matter what value we give for
11275         // wantnormals and wanttangents, so this logic uses only rules applicable
11276         // to a model, knowing that they are meaningless otherwise
11277         if (ent == r_refdef.scene.worldentity)
11278                 RSurf_ActiveWorldEntity();
11279         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11280                 RSurf_ActiveModelEntity(ent, false, false, false);
11281         else if (prepass)
11282                 RSurf_ActiveModelEntity(ent, true, true, true);
11283         else if (depthonly)
11284         {
11285                 switch (vid.renderpath)
11286                 {
11287                 case RENDERPATH_GL20:
11288                 case RENDERPATH_D3D9:
11289                 case RENDERPATH_D3D10:
11290                 case RENDERPATH_D3D11:
11291                 case RENDERPATH_SOFT:
11292                 case RENDERPATH_GLES2:
11293                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11294                         break;
11295                 case RENDERPATH_GL13:
11296                 case RENDERPATH_GL11:
11297                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11298                         break;
11299                 }
11300         }
11301         else
11302         {
11303                 switch (vid.renderpath)
11304                 {
11305                 case RENDERPATH_GL20:
11306                 case RENDERPATH_D3D9:
11307                 case RENDERPATH_D3D10:
11308                 case RENDERPATH_D3D11:
11309                 case RENDERPATH_SOFT:
11310                 case RENDERPATH_GLES2:
11311                         RSurf_ActiveModelEntity(ent, true, true, false);
11312                         break;
11313                 case RENDERPATH_GL13:
11314                 case RENDERPATH_GL11:
11315                         RSurf_ActiveModelEntity(ent, true, false, false);
11316                         break;
11317                 }
11318         }
11319
11320         surfaces = model->data_surfaces;
11321         update = model->brushq1.lightmapupdateflags;
11322
11323         // update light styles
11324         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11325         {
11326                 model_brush_lightstyleinfo_t *style;
11327                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11328                 {
11329                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11330                         {
11331                                 int *list = style->surfacelist;
11332                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11333                                 for (j = 0;j < style->numsurfaces;j++)
11334                                         update[list[j]] = true;
11335                         }
11336                 }
11337         }
11338
11339         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11340
11341         if (debug)
11342         {
11343                 R_DrawDebugModel();
11344                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11345                 return;
11346         }
11347
11348         rsurface.lightmaptexture = NULL;
11349         rsurface.deluxemaptexture = NULL;
11350         rsurface.uselightmaptexture = false;
11351         rsurface.texture = NULL;
11352         rsurface.rtlight = NULL;
11353         numsurfacelist = 0;
11354         // add visible surfaces to draw list
11355         for (i = 0;i < model->nummodelsurfaces;i++)
11356                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11357         // don't do anything if there were no surfaces
11358         if (!numsurfacelist)
11359         {
11360                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11361                 return;
11362         }
11363         // update lightmaps if needed
11364         if (update)
11365         {
11366                 int updated = 0;
11367                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11368                 {
11369                         if (update[j])
11370                         {
11371                                 updated++;
11372                                 R_BuildLightMap(ent, surfaces + j);
11373                         }
11374                 }
11375         }
11376         if (update)
11377                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11378                         if (update[j])
11379                                 R_BuildLightMap(ent, surfaces + j);
11380         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11381
11382         // add to stats if desired
11383         if (r_speeds.integer && !skysurfaces && !depthonly)
11384         {
11385                 r_refdef.stats.entities_surfaces += numsurfacelist;
11386                 for (j = 0;j < numsurfacelist;j++)
11387                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11388         }
11389
11390         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11391 }
11392
11393 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11394 {
11395         static texture_t texture;
11396         static msurface_t surface;
11397         const msurface_t *surfacelist = &surface;
11398
11399         // fake enough texture and surface state to render this geometry
11400
11401         texture.update_lastrenderframe = -1; // regenerate this texture
11402         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11403         texture.currentskinframe = skinframe;
11404         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11405         texture.offsetmapping = OFFSETMAPPING_OFF;
11406         texture.offsetscale = 1;
11407         texture.specularscalemod = 1;
11408         texture.specularpowermod = 1;
11409
11410         surface.texture = &texture;
11411         surface.num_triangles = numtriangles;
11412         surface.num_firsttriangle = firsttriangle;
11413         surface.num_vertices = numvertices;
11414         surface.num_firstvertex = firstvertex;
11415
11416         // now render it
11417         rsurface.texture = R_GetCurrentTexture(surface.texture);
11418         rsurface.lightmaptexture = NULL;
11419         rsurface.deluxemaptexture = NULL;
11420         rsurface.uselightmaptexture = false;
11421         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11422 }
11423
11424 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)
11425 {
11426         static msurface_t surface;
11427         const msurface_t *surfacelist = &surface;
11428
11429         // fake enough texture and surface state to render this geometry
11430         surface.texture = texture;
11431         surface.num_triangles = numtriangles;
11432         surface.num_firsttriangle = firsttriangle;
11433         surface.num_vertices = numvertices;
11434         surface.num_firstvertex = firstvertex;
11435
11436         // now render it
11437         rsurface.texture = R_GetCurrentTexture(surface.texture);
11438         rsurface.lightmaptexture = NULL;
11439         rsurface.deluxemaptexture = NULL;
11440         rsurface.uselightmaptexture = false;
11441         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11442 }