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