]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
added r_viewfbo and r_viewscale cvars - the former allows use of
[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
147 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)"};
148 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
149 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)"};
150 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
151 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)"};
152 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
153 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
154 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)"};
155 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)"};
156 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)"};
157 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)"};
158 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)"};
159 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)"};
160 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)"};
161 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)"};
162
163 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)"};
164 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
165 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"};
166 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
167 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
168 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
169
170 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
171 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
172 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
173 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
174
175 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
176 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
177 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
178 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
179 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
180 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
181 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
182
183 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
184 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
185 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
186 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)"};
187 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
188 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
189 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
190 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
191 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
192 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
193
194 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"};
195
196 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"};
197
198 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
199
200 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
201 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"};
202 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
203 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
204 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
205 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
206 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)"};
207 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
208 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
209
210 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
211 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"};
212
213 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."};
214
215 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)"};
216
217 extern cvar_t v_glslgamma;
218
219 extern qboolean v_flipped_state;
220
221 static struct r_bloomstate_s
222 {
223         qboolean enabled;
224         qboolean hdr;
225
226         int bloomwidth, bloomheight;
227
228         textype_t texturetype;
229         int viewfbo; // used to check if r_viewfbo cvar has changed
230
231         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
232         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
233         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
234
235         int screentexturewidth, screentextureheight;
236         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
237
238         int bloomtexturewidth, bloomtextureheight;
239         rtexture_t *texture_bloom;
240
241         // arrays for rendering the screen passes
242         float screentexcoord2f[8];
243         float bloomtexcoord2f[8];
244         float offsettexcoord2f[8];
245
246         r_viewport_t viewport;
247 }
248 r_bloomstate;
249
250 r_waterstate_t r_waterstate;
251
252 /// shadow volume bsp struct with automatically growing nodes buffer
253 svbsp_t r_svbsp;
254
255 rtexture_t *r_texture_blanknormalmap;
256 rtexture_t *r_texture_white;
257 rtexture_t *r_texture_grey128;
258 rtexture_t *r_texture_black;
259 rtexture_t *r_texture_notexture;
260 rtexture_t *r_texture_whitecube;
261 rtexture_t *r_texture_normalizationcube;
262 rtexture_t *r_texture_fogattenuation;
263 rtexture_t *r_texture_fogheighttexture;
264 rtexture_t *r_texture_gammaramps;
265 unsigned int r_texture_gammaramps_serial;
266 //rtexture_t *r_texture_fogintensity;
267 rtexture_t *r_texture_reflectcube;
268
269 // TODO: hash lookups?
270 typedef struct cubemapinfo_s
271 {
272         char basename[64];
273         rtexture_t *texture;
274 }
275 cubemapinfo_t;
276
277 int r_texture_numcubemaps;
278 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
279
280 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
281 unsigned int r_numqueries;
282 unsigned int r_maxqueries;
283
284 typedef struct r_qwskincache_s
285 {
286         char name[MAX_QPATH];
287         skinframe_t *skinframe;
288 }
289 r_qwskincache_t;
290
291 static r_qwskincache_t *r_qwskincache;
292 static int r_qwskincache_size;
293
294 /// vertex coordinates for a quad that covers the screen exactly
295 extern const float r_screenvertex3f[12];
296 extern const float r_d3dscreenvertex3f[12];
297 const float r_screenvertex3f[12] =
298 {
299         0, 0, 0,
300         1, 0, 0,
301         1, 1, 0,
302         0, 1, 0
303 };
304 const float r_d3dscreenvertex3f[12] =
305 {
306         0, 1, 0,
307         1, 1, 0,
308         1, 0, 0,
309         0, 0, 0
310 };
311
312 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
313 {
314         int i;
315         for (i = 0;i < verts;i++)
316         {
317                 out[0] = in[0] * r;
318                 out[1] = in[1] * g;
319                 out[2] = in[2] * b;
320                 out[3] = in[3];
321                 in += 4;
322                 out += 4;
323         }
324 }
325
326 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
327 {
328         int i;
329         for (i = 0;i < verts;i++)
330         {
331                 out[0] = r;
332                 out[1] = g;
333                 out[2] = b;
334                 out[3] = a;
335                 out += 4;
336         }
337 }
338
339 // FIXME: move this to client?
340 void FOG_clear(void)
341 {
342         if (gamemode == GAME_NEHAHRA)
343         {
344                 Cvar_Set("gl_fogenable", "0");
345                 Cvar_Set("gl_fogdensity", "0.2");
346                 Cvar_Set("gl_fogred", "0.3");
347                 Cvar_Set("gl_foggreen", "0.3");
348                 Cvar_Set("gl_fogblue", "0.3");
349         }
350         r_refdef.fog_density = 0;
351         r_refdef.fog_red = 0;
352         r_refdef.fog_green = 0;
353         r_refdef.fog_blue = 0;
354         r_refdef.fog_alpha = 1;
355         r_refdef.fog_start = 0;
356         r_refdef.fog_end = 16384;
357         r_refdef.fog_height = 1<<30;
358         r_refdef.fog_fadedepth = 128;
359         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
360 }
361
362 static void R_BuildBlankTextures(void)
363 {
364         unsigned char data[4];
365         data[2] = 128; // normal X
366         data[1] = 128; // normal Y
367         data[0] = 255; // normal Z
368         data[3] = 128; // height
369         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 255;
371         data[1] = 255;
372         data[2] = 255;
373         data[3] = 255;
374         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 128;
376         data[1] = 128;
377         data[2] = 128;
378         data[3] = 255;
379         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 0;
381         data[1] = 0;
382         data[2] = 0;
383         data[3] = 255;
384         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildNoTexture(void)
388 {
389         int x, y;
390         unsigned char pix[16][16][4];
391         // this makes a light grey/dark grey checkerboard texture
392         for (y = 0;y < 16;y++)
393         {
394                 for (x = 0;x < 16;x++)
395                 {
396                         if ((y < 8) ^ (x < 8))
397                         {
398                                 pix[y][x][0] = 128;
399                                 pix[y][x][1] = 128;
400                                 pix[y][x][2] = 128;
401                                 pix[y][x][3] = 255;
402                         }
403                         else
404                         {
405                                 pix[y][x][0] = 64;
406                                 pix[y][x][1] = 64;
407                                 pix[y][x][2] = 64;
408                                 pix[y][x][3] = 255;
409                         }
410                 }
411         }
412         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
413 }
414
415 static void R_BuildWhiteCube(void)
416 {
417         unsigned char data[6*1*1*4];
418         memset(data, 255, sizeof(data));
419         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
420 }
421
422 static void R_BuildNormalizationCube(void)
423 {
424         int x, y, side;
425         vec3_t v;
426         vec_t s, t, intensity;
427 #define NORMSIZE 64
428         unsigned char *data;
429         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
430         for (side = 0;side < 6;side++)
431         {
432                 for (y = 0;y < NORMSIZE;y++)
433                 {
434                         for (x = 0;x < NORMSIZE;x++)
435                         {
436                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
437                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
438                                 switch(side)
439                                 {
440                                 default:
441                                 case 0:
442                                         v[0] = 1;
443                                         v[1] = -t;
444                                         v[2] = -s;
445                                         break;
446                                 case 1:
447                                         v[0] = -1;
448                                         v[1] = -t;
449                                         v[2] = s;
450                                         break;
451                                 case 2:
452                                         v[0] = s;
453                                         v[1] = 1;
454                                         v[2] = t;
455                                         break;
456                                 case 3:
457                                         v[0] = s;
458                                         v[1] = -1;
459                                         v[2] = -t;
460                                         break;
461                                 case 4:
462                                         v[0] = s;
463                                         v[1] = -t;
464                                         v[2] = 1;
465                                         break;
466                                 case 5:
467                                         v[0] = -s;
468                                         v[1] = -t;
469                                         v[2] = -1;
470                                         break;
471                                 }
472                                 intensity = 127.0f / sqrt(DotProduct(v, v));
473                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
474                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
475                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
476                                 data[((side*64+y)*64+x)*4+3] = 255;
477                         }
478                 }
479         }
480         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
481         Mem_Free(data);
482 }
483
484 static void R_BuildFogTexture(void)
485 {
486         int x, b;
487 #define FOGWIDTH 256
488         unsigned char data1[FOGWIDTH][4];
489         //unsigned char data2[FOGWIDTH][4];
490         double d, r, alpha;
491
492         r_refdef.fogmasktable_start = r_refdef.fog_start;
493         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
494         r_refdef.fogmasktable_range = r_refdef.fogrange;
495         r_refdef.fogmasktable_density = r_refdef.fog_density;
496
497         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
498         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
499         {
500                 d = (x * r - r_refdef.fogmasktable_start);
501                 if(developer_extra.integer)
502                         Con_DPrintf("%f ", d);
503                 d = max(0, d);
504                 if (r_fog_exp2.integer)
505                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
506                 else
507                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
508                 if(developer_extra.integer)
509                         Con_DPrintf(" : %f ", alpha);
510                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
511                 if(developer_extra.integer)
512                         Con_DPrintf(" = %f\n", alpha);
513                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
514         }
515
516         for (x = 0;x < FOGWIDTH;x++)
517         {
518                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
519                 data1[x][0] = b;
520                 data1[x][1] = b;
521                 data1[x][2] = b;
522                 data1[x][3] = 255;
523                 //data2[x][0] = 255 - b;
524                 //data2[x][1] = 255 - b;
525                 //data2[x][2] = 255 - b;
526                 //data2[x][3] = 255;
527         }
528         if (r_texture_fogattenuation)
529         {
530                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
531                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
532         }
533         else
534         {
535                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
536                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
537         }
538 }
539
540 static void R_BuildFogHeightTexture(void)
541 {
542         unsigned char *inpixels;
543         int size;
544         int x;
545         int y;
546         int j;
547         float c[4];
548         float f;
549         inpixels = NULL;
550         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
551         if (r_refdef.fogheighttexturename[0])
552                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
553         if (!inpixels)
554         {
555                 r_refdef.fog_height_tablesize = 0;
556                 if (r_texture_fogheighttexture)
557                         R_FreeTexture(r_texture_fogheighttexture);
558                 r_texture_fogheighttexture = NULL;
559                 if (r_refdef.fog_height_table2d)
560                         Mem_Free(r_refdef.fog_height_table2d);
561                 r_refdef.fog_height_table2d = NULL;
562                 if (r_refdef.fog_height_table1d)
563                         Mem_Free(r_refdef.fog_height_table1d);
564                 r_refdef.fog_height_table1d = NULL;
565                 return;
566         }
567         size = image_width;
568         r_refdef.fog_height_tablesize = size;
569         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
570         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
571         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
572         Mem_Free(inpixels);
573         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
574         // average fog color table accounting for every fog layer between a point
575         // and the camera.  (Note: attenuation is handled separately!)
576         for (y = 0;y < size;y++)
577         {
578                 for (x = 0;x < size;x++)
579                 {
580                         Vector4Clear(c);
581                         f = 0;
582                         if (x < y)
583                         {
584                                 for (j = x;j <= y;j++)
585                                 {
586                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
587                                         f++;
588                                 }
589                         }
590                         else
591                         {
592                                 for (j = x;j >= y;j--)
593                                 {
594                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
595                                         f++;
596                                 }
597                         }
598                         f = 1.0f / f;
599                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
600                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
601                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
602                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
603                 }
604         }
605         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
606 }
607
608 //=======================================================================================================================================================
609
610 static const char *builtinshaderstring =
611 #include "shader_glsl.h"
612 ;
613
614 const char *builtinhlslshaderstring =
615 #include "shader_hlsl.h"
616 ;
617
618 char *glslshaderstring = NULL;
619 char *hlslshaderstring = NULL;
620
621 //=======================================================================================================================================================
622
623 typedef struct shaderpermutationinfo_s
624 {
625         const char *pretext;
626         const char *name;
627 }
628 shaderpermutationinfo_t;
629
630 typedef struct shadermodeinfo_s
631 {
632         const char *vertexfilename;
633         const char *geometryfilename;
634         const char *fragmentfilename;
635         const char *pretext;
636         const char *name;
637 }
638 shadermodeinfo_t;
639
640 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
641 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
642 {
643         {"#define USEDIFFUSE\n", " diffuse"},
644         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
645         {"#define USEVIEWTINT\n", " viewtint"},
646         {"#define USECOLORMAPPING\n", " colormapping"},
647         {"#define USESATURATION\n", " saturation"},
648         {"#define USEFOGINSIDE\n", " foginside"},
649         {"#define USEFOGOUTSIDE\n", " fogoutside"},
650         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
651         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
652         {"#define USEGAMMARAMPS\n", " gammaramps"},
653         {"#define USECUBEFILTER\n", " cubefilter"},
654         {"#define USEGLOW\n", " glow"},
655         {"#define USEBLOOM\n", " bloom"},
656         {"#define USESPECULAR\n", " specular"},
657         {"#define USEPOSTPROCESSING\n", " postprocessing"},
658         {"#define USEREFLECTION\n", " reflection"},
659         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
660         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
661         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
662         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
663         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
664         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
665         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
666         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
667         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
668         {"#define USEALPHAKILL\n", " alphakill"},
669         {"#define USEREFLECTCUBE\n", " reflectcube"},
670         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
671         {"#define USEBOUNCEGRID\n", " bouncegrid"},
672         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
673 };
674
675 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
676 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
677 {
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
680         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
694 };
695
696 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
697 {
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
714 };
715
716 struct r_glsl_permutation_s;
717 typedef struct r_glsl_permutation_s
718 {
719         /// hash lookup data
720         struct r_glsl_permutation_s *hashnext;
721         unsigned int mode;
722         unsigned int permutation;
723
724         /// indicates if we have tried compiling this permutation already
725         qboolean compiled;
726         /// 0 if compilation failed
727         int program;
728         // texture units assigned to each detected uniform
729         int tex_Texture_First;
730         int tex_Texture_Second;
731         int tex_Texture_GammaRamps;
732         int tex_Texture_Normal;
733         int tex_Texture_Color;
734         int tex_Texture_Gloss;
735         int tex_Texture_Glow;
736         int tex_Texture_SecondaryNormal;
737         int tex_Texture_SecondaryColor;
738         int tex_Texture_SecondaryGloss;
739         int tex_Texture_SecondaryGlow;
740         int tex_Texture_Pants;
741         int tex_Texture_Shirt;
742         int tex_Texture_FogHeightTexture;
743         int tex_Texture_FogMask;
744         int tex_Texture_Lightmap;
745         int tex_Texture_Deluxemap;
746         int tex_Texture_Attenuation;
747         int tex_Texture_Cube;
748         int tex_Texture_Refraction;
749         int tex_Texture_Reflection;
750         int tex_Texture_ShadowMap2D;
751         int tex_Texture_CubeProjection;
752         int tex_Texture_ScreenDepth;
753         int tex_Texture_ScreenNormalMap;
754         int tex_Texture_ScreenDiffuse;
755         int tex_Texture_ScreenSpecular;
756         int tex_Texture_ReflectMask;
757         int tex_Texture_ReflectCube;
758         int tex_Texture_BounceGrid;
759         /// locations of detected uniforms in program object, or -1 if not found
760         int loc_Texture_First;
761         int loc_Texture_Second;
762         int loc_Texture_GammaRamps;
763         int loc_Texture_Normal;
764         int loc_Texture_Color;
765         int loc_Texture_Gloss;
766         int loc_Texture_Glow;
767         int loc_Texture_SecondaryNormal;
768         int loc_Texture_SecondaryColor;
769         int loc_Texture_SecondaryGloss;
770         int loc_Texture_SecondaryGlow;
771         int loc_Texture_Pants;
772         int loc_Texture_Shirt;
773         int loc_Texture_FogHeightTexture;
774         int loc_Texture_FogMask;
775         int loc_Texture_Lightmap;
776         int loc_Texture_Deluxemap;
777         int loc_Texture_Attenuation;
778         int loc_Texture_Cube;
779         int loc_Texture_Refraction;
780         int loc_Texture_Reflection;
781         int loc_Texture_ShadowMap2D;
782         int loc_Texture_CubeProjection;
783         int loc_Texture_ScreenDepth;
784         int loc_Texture_ScreenNormalMap;
785         int loc_Texture_ScreenDiffuse;
786         int loc_Texture_ScreenSpecular;
787         int loc_Texture_ReflectMask;
788         int loc_Texture_ReflectCube;
789         int loc_Texture_BounceGrid;
790         int loc_Alpha;
791         int loc_BloomBlur_Parameters;
792         int loc_ClientTime;
793         int loc_Color_Ambient;
794         int loc_Color_Diffuse;
795         int loc_Color_Specular;
796         int loc_Color_Glow;
797         int loc_Color_Pants;
798         int loc_Color_Shirt;
799         int loc_DeferredColor_Ambient;
800         int loc_DeferredColor_Diffuse;
801         int loc_DeferredColor_Specular;
802         int loc_DeferredMod_Diffuse;
803         int loc_DeferredMod_Specular;
804         int loc_DistortScaleRefractReflect;
805         int loc_EyePosition;
806         int loc_FogColor;
807         int loc_FogHeightFade;
808         int loc_FogPlane;
809         int loc_FogPlaneViewDist;
810         int loc_FogRangeRecip;
811         int loc_LightColor;
812         int loc_LightDir;
813         int loc_LightPosition;
814         int loc_OffsetMapping_ScaleSteps;
815         int loc_PixelSize;
816         int loc_ReflectColor;
817         int loc_ReflectFactor;
818         int loc_ReflectOffset;
819         int loc_RefractColor;
820         int loc_Saturation;
821         int loc_ScreenCenterRefractReflect;
822         int loc_ScreenScaleRefractReflect;
823         int loc_ScreenToDepth;
824         int loc_ShadowMap_Parameters;
825         int loc_ShadowMap_TextureScale;
826         int loc_SpecularPower;
827         int loc_UserVec1;
828         int loc_UserVec2;
829         int loc_UserVec3;
830         int loc_UserVec4;
831         int loc_ViewTintColor;
832         int loc_ViewToLight;
833         int loc_ModelToLight;
834         int loc_TexMatrix;
835         int loc_BackgroundTexMatrix;
836         int loc_ModelViewProjectionMatrix;
837         int loc_ModelViewMatrix;
838         int loc_PixelToScreenTexCoord;
839         int loc_ModelToReflectCube;
840         int loc_ShadowMapMatrix;
841         int loc_BloomColorSubtract;
842         int loc_NormalmapScrollBlend;
843         int loc_BounceGridMatrix;
844         int loc_BounceGridIntensity;
845 }
846 r_glsl_permutation_t;
847
848 #define SHADERPERMUTATION_HASHSIZE 256
849
850
851 // non-degradable "lightweight" shader parameters to keep the permutations simpler
852 // these can NOT degrade! only use for simple stuff
853 enum
854 {
855         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
856         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
857         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
858         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
859         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
861         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
862 };
863 #define SHADERSTATICPARMS_COUNT 7
864
865 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
866 static int shaderstaticparms_count = 0;
867
868 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
869 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
870 qboolean R_CompileShader_CheckStaticParms(void)
871 {
872         static int r_compileshader_staticparms_save[1];
873         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
874         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
875
876         // detect all
877         if (r_glsl_saturation_redcompensate.integer)
878                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
879         if (r_glsl_vertextextureblend_usebothalphas.integer)
880                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
881         if (r_shadow_glossexact.integer)
882                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
883         if (r_glsl_postprocess.integer)
884         {
885                 if (r_glsl_postprocess_uservec1_enable.integer)
886                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
887                 if (r_glsl_postprocess_uservec2_enable.integer)
888                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
889                 if (r_glsl_postprocess_uservec3_enable.integer)
890                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
891                 if (r_glsl_postprocess_uservec4_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
893         }
894         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
895 }
896
897 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
898         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
899                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
900         else \
901                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
902 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
903 {
904         shaderstaticparms_count = 0;
905
906         // emit all
907         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
908         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
909         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
910         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
911         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
912         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
914 }
915
916 /// information about each possible shader permutation
917 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
918 /// currently selected permutation
919 r_glsl_permutation_t *r_glsl_permutation;
920 /// storage for permutations linked in the hash table
921 memexpandablearray_t r_glsl_permutationarray;
922
923 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
924 {
925         //unsigned int hashdepth = 0;
926         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
927         r_glsl_permutation_t *p;
928         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
929         {
930                 if (p->mode == mode && p->permutation == permutation)
931                 {
932                         //if (hashdepth > 10)
933                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
934                         return p;
935                 }
936                 //hashdepth++;
937         }
938         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
939         p->mode = mode;
940         p->permutation = permutation;
941         p->hashnext = r_glsl_permutationhash[mode][hashindex];
942         r_glsl_permutationhash[mode][hashindex] = p;
943         //if (hashdepth > 10)
944         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
945         return p;
946 }
947
948 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
949 {
950         char *shaderstring;
951         if (!filename || !filename[0])
952                 return NULL;
953         if (!strcmp(filename, "glsl/default.glsl"))
954         {
955                 if (!glslshaderstring)
956                 {
957                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
958                         if (glslshaderstring)
959                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
960                         else
961                                 glslshaderstring = (char *)builtinshaderstring;
962                 }
963                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
964                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
965                 return shaderstring;
966         }
967         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
968         if (shaderstring)
969         {
970                 if (printfromdisknotice)
971                         Con_DPrintf("from disk %s... ", filename);
972                 return shaderstring;
973         }
974         return shaderstring;
975 }
976
977 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
978 {
979         int i;
980         int sampler;
981         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
982         char *vertexstring, *geometrystring, *fragmentstring;
983         char permutationname[256];
984         int vertstrings_count = 0;
985         int geomstrings_count = 0;
986         int fragstrings_count = 0;
987         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
988         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
989         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
990
991         if (p->compiled)
992                 return;
993         p->compiled = true;
994         p->program = 0;
995
996         permutationname[0] = 0;
997         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
998         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
999         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1000
1001         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1002
1003         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1004         if(vid.support.gl20shaders130)
1005         {
1006                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1007                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1008                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1009                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1010                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1011                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1012         }
1013
1014         // the first pretext is which type of shader to compile as
1015         // (later these will all be bound together as a program object)
1016         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1017         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1018         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1019
1020         // the second pretext is the mode (for example a light source)
1021         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1022         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1023         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1024         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1025
1026         // now add all the permutation pretexts
1027         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1028         {
1029                 if (permutation & (1<<i))
1030                 {
1031                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1032                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1033                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1034                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1035                 }
1036                 else
1037                 {
1038                         // keep line numbers correct
1039                         vertstrings_list[vertstrings_count++] = "\n";
1040                         geomstrings_list[geomstrings_count++] = "\n";
1041                         fragstrings_list[fragstrings_count++] = "\n";
1042                 }
1043         }
1044
1045         // add static parms
1046         R_CompileShader_AddStaticParms(mode, permutation);
1047         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1048         vertstrings_count += shaderstaticparms_count;
1049         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1050         geomstrings_count += shaderstaticparms_count;
1051         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1052         fragstrings_count += shaderstaticparms_count;
1053
1054         // now append the shader text itself
1055         vertstrings_list[vertstrings_count++] = vertexstring;
1056         geomstrings_list[geomstrings_count++] = geometrystring;
1057         fragstrings_list[fragstrings_count++] = fragmentstring;
1058
1059         // if any sources were NULL, clear the respective list
1060         if (!vertexstring)
1061                 vertstrings_count = 0;
1062         if (!geometrystring)
1063                 geomstrings_count = 0;
1064         if (!fragmentstring)
1065                 fragstrings_count = 0;
1066
1067         // compile the shader program
1068         if (vertstrings_count + geomstrings_count + fragstrings_count)
1069                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1070         if (p->program)
1071         {
1072                 CHECKGLERROR
1073                 qglUseProgram(p->program);CHECKGLERROR
1074                 // look up all the uniform variable names we care about, so we don't
1075                 // have to look them up every time we set them
1076
1077                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1078                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1079                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1080                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1081                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1082                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1083                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1084                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1085                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1086                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1087                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1088                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1089                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1090                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1091                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1092                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1093                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1094                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1095                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1096                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1097                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1098                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1099                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1100                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1101                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1102                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1103                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1104                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1105                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1106                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1107                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1108                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1109                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1110                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1111                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1112                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1113                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1114                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1115                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1116                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1117                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1118                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1119                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1120                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1121                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1122                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1123                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1124                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1125                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1126                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1127                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1128                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1129                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1130                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1131                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1132                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1133                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1134                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1135                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1136                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1137                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1138                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1139                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1140                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1141                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1142                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1143                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1144                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1145                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1146                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1147                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1148                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1149                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1150                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1151                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1152                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1153                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1154                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1155                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1156                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1157                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1158                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1159                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1160                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1161                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1162                 // initialize the samplers to refer to the texture units we use
1163                 p->tex_Texture_First = -1;
1164                 p->tex_Texture_Second = -1;
1165                 p->tex_Texture_GammaRamps = -1;
1166                 p->tex_Texture_Normal = -1;
1167                 p->tex_Texture_Color = -1;
1168                 p->tex_Texture_Gloss = -1;
1169                 p->tex_Texture_Glow = -1;
1170                 p->tex_Texture_SecondaryNormal = -1;
1171                 p->tex_Texture_SecondaryColor = -1;
1172                 p->tex_Texture_SecondaryGloss = -1;
1173                 p->tex_Texture_SecondaryGlow = -1;
1174                 p->tex_Texture_Pants = -1;
1175                 p->tex_Texture_Shirt = -1;
1176                 p->tex_Texture_FogHeightTexture = -1;
1177                 p->tex_Texture_FogMask = -1;
1178                 p->tex_Texture_Lightmap = -1;
1179                 p->tex_Texture_Deluxemap = -1;
1180                 p->tex_Texture_Attenuation = -1;
1181                 p->tex_Texture_Cube = -1;
1182                 p->tex_Texture_Refraction = -1;
1183                 p->tex_Texture_Reflection = -1;
1184                 p->tex_Texture_ShadowMap2D = -1;
1185                 p->tex_Texture_CubeProjection = -1;
1186                 p->tex_Texture_ScreenDepth = -1;
1187                 p->tex_Texture_ScreenNormalMap = -1;
1188                 p->tex_Texture_ScreenDiffuse = -1;
1189                 p->tex_Texture_ScreenSpecular = -1;
1190                 p->tex_Texture_ReflectMask = -1;
1191                 p->tex_Texture_ReflectCube = -1;
1192                 p->tex_Texture_BounceGrid = -1;
1193                 sampler = 0;
1194                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1195                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1196                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1197                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1198                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1199                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1200                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1201                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1202                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1203                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1204                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1205                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1206                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1207                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1208                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1209                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1210                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1211                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1212                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1213                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1214                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1215                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1216                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1217                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1218                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1219                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1220                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1221                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1222                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1223                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1224                 CHECKGLERROR
1225                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1226         }
1227         else
1228                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1229
1230         // free the strings
1231         if (vertexstring)
1232                 Mem_Free(vertexstring);
1233         if (geometrystring)
1234                 Mem_Free(geometrystring);
1235         if (fragmentstring)
1236                 Mem_Free(fragmentstring);
1237 }
1238
1239 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1240 {
1241         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1242         if (r_glsl_permutation != perm)
1243         {
1244                 r_glsl_permutation = perm;
1245                 if (!r_glsl_permutation->program)
1246                 {
1247                         if (!r_glsl_permutation->compiled)
1248                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1249                         if (!r_glsl_permutation->program)
1250                         {
1251                                 // remove features until we find a valid permutation
1252                                 int i;
1253                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1254                                 {
1255                                         // reduce i more quickly whenever it would not remove any bits
1256                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1257                                         if (!(permutation & j))
1258                                                 continue;
1259                                         permutation -= j;
1260                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1261                                         if (!r_glsl_permutation->compiled)
1262                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1263                                         if (r_glsl_permutation->program)
1264                                                 break;
1265                                 }
1266                                 if (i >= SHADERPERMUTATION_COUNT)
1267                                 {
1268                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1269                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1270                                         qglUseProgram(0);CHECKGLERROR
1271                                         return; // no bit left to clear, entire mode is broken
1272                                 }
1273                         }
1274                 }
1275                 CHECKGLERROR
1276                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1277         }
1278         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1279         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1280         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1281 }
1282
1283 #ifdef SUPPORTD3D
1284
1285 #ifdef SUPPORTD3D
1286 #include <d3d9.h>
1287 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1288 extern D3DCAPS9 vid_d3d9caps;
1289 #endif
1290
1291 struct r_hlsl_permutation_s;
1292 typedef struct r_hlsl_permutation_s
1293 {
1294         /// hash lookup data
1295         struct r_hlsl_permutation_s *hashnext;
1296         unsigned int mode;
1297         unsigned int permutation;
1298
1299         /// indicates if we have tried compiling this permutation already
1300         qboolean compiled;
1301         /// NULL if compilation failed
1302         IDirect3DVertexShader9 *vertexshader;
1303         IDirect3DPixelShader9 *pixelshader;
1304 }
1305 r_hlsl_permutation_t;
1306
1307 typedef enum D3DVSREGISTER_e
1308 {
1309         D3DVSREGISTER_TexMatrix = 0, // float4x4
1310         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1311         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1312         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1313         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1314         D3DVSREGISTER_ModelToLight = 20, // float4x4
1315         D3DVSREGISTER_EyePosition = 24,
1316         D3DVSREGISTER_FogPlane = 25,
1317         D3DVSREGISTER_LightDir = 26,
1318         D3DVSREGISTER_LightPosition = 27,
1319 }
1320 D3DVSREGISTER_t;
1321
1322 typedef enum D3DPSREGISTER_e
1323 {
1324         D3DPSREGISTER_Alpha = 0,
1325         D3DPSREGISTER_BloomBlur_Parameters = 1,
1326         D3DPSREGISTER_ClientTime = 2,
1327         D3DPSREGISTER_Color_Ambient = 3,
1328         D3DPSREGISTER_Color_Diffuse = 4,
1329         D3DPSREGISTER_Color_Specular = 5,
1330         D3DPSREGISTER_Color_Glow = 6,
1331         D3DPSREGISTER_Color_Pants = 7,
1332         D3DPSREGISTER_Color_Shirt = 8,
1333         D3DPSREGISTER_DeferredColor_Ambient = 9,
1334         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1335         D3DPSREGISTER_DeferredColor_Specular = 11,
1336         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1337         D3DPSREGISTER_DeferredMod_Specular = 13,
1338         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1339         D3DPSREGISTER_EyePosition = 15, // unused
1340         D3DPSREGISTER_FogColor = 16,
1341         D3DPSREGISTER_FogHeightFade = 17,
1342         D3DPSREGISTER_FogPlane = 18,
1343         D3DPSREGISTER_FogPlaneViewDist = 19,
1344         D3DPSREGISTER_FogRangeRecip = 20,
1345         D3DPSREGISTER_LightColor = 21,
1346         D3DPSREGISTER_LightDir = 22, // unused
1347         D3DPSREGISTER_LightPosition = 23,
1348         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1349         D3DPSREGISTER_PixelSize = 25,
1350         D3DPSREGISTER_ReflectColor = 26,
1351         D3DPSREGISTER_ReflectFactor = 27,
1352         D3DPSREGISTER_ReflectOffset = 28,
1353         D3DPSREGISTER_RefractColor = 29,
1354         D3DPSREGISTER_Saturation = 30,
1355         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1356         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1357         D3DPSREGISTER_ScreenToDepth = 33,
1358         D3DPSREGISTER_ShadowMap_Parameters = 34,
1359         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1360         D3DPSREGISTER_SpecularPower = 36,
1361         D3DPSREGISTER_UserVec1 = 37,
1362         D3DPSREGISTER_UserVec2 = 38,
1363         D3DPSREGISTER_UserVec3 = 39,
1364         D3DPSREGISTER_UserVec4 = 40,
1365         D3DPSREGISTER_ViewTintColor = 41,
1366         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1367         D3DPSREGISTER_BloomColorSubtract = 43,
1368         D3DPSREGISTER_ViewToLight = 44, // float4x4
1369         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1370         D3DPSREGISTER_NormalmapScrollBlend = 52,
1371         // next at 53
1372 }
1373 D3DPSREGISTER_t;
1374
1375 /// information about each possible shader permutation
1376 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1377 /// currently selected permutation
1378 r_hlsl_permutation_t *r_hlsl_permutation;
1379 /// storage for permutations linked in the hash table
1380 memexpandablearray_t r_hlsl_permutationarray;
1381
1382 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1383 {
1384         //unsigned int hashdepth = 0;
1385         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1386         r_hlsl_permutation_t *p;
1387         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1388         {
1389                 if (p->mode == mode && p->permutation == permutation)
1390                 {
1391                         //if (hashdepth > 10)
1392                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1393                         return p;
1394                 }
1395                 //hashdepth++;
1396         }
1397         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1398         p->mode = mode;
1399         p->permutation = permutation;
1400         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1401         r_hlsl_permutationhash[mode][hashindex] = p;
1402         //if (hashdepth > 10)
1403         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1404         return p;
1405 }
1406
1407 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1408 {
1409         char *shaderstring;
1410         if (!filename || !filename[0])
1411                 return NULL;
1412         if (!strcmp(filename, "hlsl/default.hlsl"))
1413         {
1414                 if (!hlslshaderstring)
1415                 {
1416                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1417                         if (hlslshaderstring)
1418                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1419                         else
1420                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1421                 }
1422                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1423                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1424                 return shaderstring;
1425         }
1426         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1427         if (shaderstring)
1428         {
1429                 if (printfromdisknotice)
1430                         Con_DPrintf("from disk %s... ", filename);
1431                 return shaderstring;
1432         }
1433         return shaderstring;
1434 }
1435
1436 #include <d3dx9.h>
1437 //#include <d3dx9shader.h>
1438 //#include <d3dx9mesh.h>
1439
1440 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1441 {
1442         DWORD *vsbin = NULL;
1443         DWORD *psbin = NULL;
1444         fs_offset_t vsbinsize;
1445         fs_offset_t psbinsize;
1446 //      IDirect3DVertexShader9 *vs = NULL;
1447 //      IDirect3DPixelShader9 *ps = NULL;
1448         ID3DXBuffer *vslog = NULL;
1449         ID3DXBuffer *vsbuffer = NULL;
1450         ID3DXConstantTable *vsconstanttable = NULL;
1451         ID3DXBuffer *pslog = NULL;
1452         ID3DXBuffer *psbuffer = NULL;
1453         ID3DXConstantTable *psconstanttable = NULL;
1454         int vsresult = 0;
1455         int psresult = 0;
1456         char temp[MAX_INPUTLINE];
1457         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1458         qboolean debugshader = gl_paranoid.integer != 0;
1459         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1460         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1461         if (!debugshader)
1462         {
1463                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1464                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1465         }
1466         if ((!vsbin && vertstring) || (!psbin && fragstring))
1467         {
1468                 const char* dllnames_d3dx9 [] =
1469                 {
1470                         "d3dx9_43.dll",
1471                         "d3dx9_42.dll",
1472                         "d3dx9_41.dll",
1473                         "d3dx9_40.dll",
1474                         "d3dx9_39.dll",
1475                         "d3dx9_38.dll",
1476                         "d3dx9_37.dll",
1477                         "d3dx9_36.dll",
1478                         "d3dx9_35.dll",
1479                         "d3dx9_34.dll",
1480                         "d3dx9_33.dll",
1481                         "d3dx9_32.dll",
1482                         "d3dx9_31.dll",
1483                         "d3dx9_30.dll",
1484                         "d3dx9_29.dll",
1485                         "d3dx9_28.dll",
1486                         "d3dx9_27.dll",
1487                         "d3dx9_26.dll",
1488                         "d3dx9_25.dll",
1489                         "d3dx9_24.dll",
1490                         NULL
1491                 };
1492                 dllhandle_t d3dx9_dll = NULL;
1493                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1494                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1495                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1496                 dllfunction_t d3dx9_dllfuncs[] =
1497                 {
1498                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1499                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1500                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1501                         {NULL, NULL}
1502                 };
1503                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1504                 {
1505                         DWORD shaderflags = 0;
1506                         if (debugshader)
1507                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1508                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1509                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1510                         if (vertstring && vertstring[0])
1511                         {
1512                                 if (debugshader)
1513                                 {
1514 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1515 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1516                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1517                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1518                                 }
1519                                 else
1520                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1521                                 if (vsbuffer)
1522                                 {
1523                                         vsbinsize = vsbuffer->GetBufferSize();
1524                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1525                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1526                                         vsbuffer->Release();
1527                                 }
1528                                 if (vslog)
1529                                 {
1530                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1531                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1532                                         vslog->Release();
1533                                 }
1534                         }
1535                         if (fragstring && fragstring[0])
1536                         {
1537                                 if (debugshader)
1538                                 {
1539 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1540 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1541                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1542                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1543                                 }
1544                                 else
1545                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1546                                 if (psbuffer)
1547                                 {
1548                                         psbinsize = psbuffer->GetBufferSize();
1549                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1550                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1551                                         psbuffer->Release();
1552                                 }
1553                                 if (pslog)
1554                                 {
1555                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1556                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1557                                         pslog->Release();
1558                                 }
1559                         }
1560                         Sys_UnloadLibrary(&d3dx9_dll);
1561                 }
1562                 else
1563                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1564         }
1565         if (vsbin && psbin)
1566         {
1567                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1568                 if (FAILED(vsresult))
1569                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1570                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1571                 if (FAILED(psresult))
1572                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1573         }
1574         // free the shader data
1575         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1576         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1577 }
1578
1579 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1580 {
1581         int i;
1582         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1583         int vertstring_length = 0;
1584         int geomstring_length = 0;
1585         int fragstring_length = 0;
1586         char *t;
1587         char *vertexstring, *geometrystring, *fragmentstring;
1588         char *vertstring, *geomstring, *fragstring;
1589         char permutationname[256];
1590         char cachename[256];
1591         int vertstrings_count = 0;
1592         int geomstrings_count = 0;
1593         int fragstrings_count = 0;
1594         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1595         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1597
1598         if (p->compiled)
1599                 return;
1600         p->compiled = true;
1601         p->vertexshader = NULL;
1602         p->pixelshader = NULL;
1603
1604         permutationname[0] = 0;
1605         cachename[0] = 0;
1606         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1607         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1608         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1609
1610         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1611         strlcat(cachename, "hlsl/", sizeof(cachename));
1612
1613         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1614         vertstrings_count = 0;
1615         geomstrings_count = 0;
1616         fragstrings_count = 0;
1617         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1618         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1619         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1620
1621         // the first pretext is which type of shader to compile as
1622         // (later these will all be bound together as a program object)
1623         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1624         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1625         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1626
1627         // the second pretext is the mode (for example a light source)
1628         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1629         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1630         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1631         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1632         strlcat(cachename, modeinfo->name, sizeof(cachename));
1633
1634         // now add all the permutation pretexts
1635         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1636         {
1637                 if (permutation & (1<<i))
1638                 {
1639                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1640                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1641                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1642                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1643                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1644                 }
1645                 else
1646                 {
1647                         // keep line numbers correct
1648                         vertstrings_list[vertstrings_count++] = "\n";
1649                         geomstrings_list[geomstrings_count++] = "\n";
1650                         fragstrings_list[fragstrings_count++] = "\n";
1651                 }
1652         }
1653
1654         // add static parms
1655         R_CompileShader_AddStaticParms(mode, permutation);
1656         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1657         vertstrings_count += shaderstaticparms_count;
1658         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1659         geomstrings_count += shaderstaticparms_count;
1660         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1661         fragstrings_count += shaderstaticparms_count;
1662
1663         // replace spaces in the cachename with _ characters
1664         for (i = 0;cachename[i];i++)
1665                 if (cachename[i] == ' ')
1666                         cachename[i] = '_';
1667
1668         // now append the shader text itself
1669         vertstrings_list[vertstrings_count++] = vertexstring;
1670         geomstrings_list[geomstrings_count++] = geometrystring;
1671         fragstrings_list[fragstrings_count++] = fragmentstring;
1672
1673         // if any sources were NULL, clear the respective list
1674         if (!vertexstring)
1675                 vertstrings_count = 0;
1676         if (!geometrystring)
1677                 geomstrings_count = 0;
1678         if (!fragmentstring)
1679                 fragstrings_count = 0;
1680
1681         vertstring_length = 0;
1682         for (i = 0;i < vertstrings_count;i++)
1683                 vertstring_length += strlen(vertstrings_list[i]);
1684         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1685         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1686                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1687
1688         geomstring_length = 0;
1689         for (i = 0;i < geomstrings_count;i++)
1690                 geomstring_length += strlen(geomstrings_list[i]);
1691         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1692         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1693                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1694
1695         fragstring_length = 0;
1696         for (i = 0;i < fragstrings_count;i++)
1697                 fragstring_length += strlen(fragstrings_list[i]);
1698         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1699         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1700                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1701
1702         // try to load the cached shader, or generate one
1703         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1704
1705         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1706                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1707         else
1708                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1709
1710         // free the strings
1711         if (vertstring)
1712                 Mem_Free(vertstring);
1713         if (geomstring)
1714                 Mem_Free(geomstring);
1715         if (fragstring)
1716                 Mem_Free(fragstring);
1717         if (vertexstring)
1718                 Mem_Free(vertexstring);
1719         if (geometrystring)
1720                 Mem_Free(geometrystring);
1721         if (fragmentstring)
1722                 Mem_Free(fragmentstring);
1723 }
1724
1725 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1726 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1727 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);}
1728 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);}
1729 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);}
1730 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);}
1731
1732 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1733 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1734 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);}
1735 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);}
1736 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);}
1737 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);}
1738
1739 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1740 {
1741         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1742         if (r_hlsl_permutation != perm)
1743         {
1744                 r_hlsl_permutation = perm;
1745                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1746                 {
1747                         if (!r_hlsl_permutation->compiled)
1748                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1749                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1750                         {
1751                                 // remove features until we find a valid permutation
1752                                 int i;
1753                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1754                                 {
1755                                         // reduce i more quickly whenever it would not remove any bits
1756                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1757                                         if (!(permutation & j))
1758                                                 continue;
1759                                         permutation -= j;
1760                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1761                                         if (!r_hlsl_permutation->compiled)
1762                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1763                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1764                                                 break;
1765                                 }
1766                                 if (i >= SHADERPERMUTATION_COUNT)
1767                                 {
1768                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1769                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1770                                         return; // no bit left to clear, entire mode is broken
1771                                 }
1772                         }
1773                 }
1774                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1775                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1776         }
1777         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1778         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1779         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1780 }
1781 #endif
1782
1783 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1784 {
1785         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1786         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1787         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1788         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1789 }
1790
1791 void R_GLSL_Restart_f(void)
1792 {
1793         unsigned int i, limit;
1794         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1795                 Mem_Free(glslshaderstring);
1796         glslshaderstring = NULL;
1797         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1798                 Mem_Free(hlslshaderstring);
1799         hlslshaderstring = NULL;
1800         switch(vid.renderpath)
1801         {
1802         case RENDERPATH_D3D9:
1803 #ifdef SUPPORTD3D
1804                 {
1805                         r_hlsl_permutation_t *p;
1806                         r_hlsl_permutation = NULL;
1807                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1808                         for (i = 0;i < limit;i++)
1809                         {
1810                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1811                                 {
1812                                         if (p->vertexshader)
1813                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1814                                         if (p->pixelshader)
1815                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1816                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1817                                 }
1818                         }
1819                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1820                 }
1821 #endif
1822                 break;
1823         case RENDERPATH_D3D10:
1824                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1825                 break;
1826         case RENDERPATH_D3D11:
1827                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1828                 break;
1829         case RENDERPATH_GL20:
1830         case RENDERPATH_GLES2:
1831                 {
1832                         r_glsl_permutation_t *p;
1833                         r_glsl_permutation = NULL;
1834                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1835                         for (i = 0;i < limit;i++)
1836                         {
1837                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1838                                 {
1839                                         GL_Backend_FreeProgram(p->program);
1840                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1841                                 }
1842                         }
1843                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1844                 }
1845                 break;
1846         case RENDERPATH_GL13:
1847         case RENDERPATH_GL11:
1848                 break;
1849         case RENDERPATH_SOFT:
1850                 break;
1851         }
1852 }
1853
1854 void R_GLSL_DumpShader_f(void)
1855 {
1856         int i;
1857         qfile_t *file;
1858
1859         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1860         if (file)
1861         {
1862                 FS_Print(file, "/* The engine may define the following macros:\n");
1863                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1864                 for (i = 0;i < SHADERMODE_COUNT;i++)
1865                         FS_Print(file, glslshadermodeinfo[i].pretext);
1866                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1867                         FS_Print(file, shaderpermutationinfo[i].pretext);
1868                 FS_Print(file, "*/\n");
1869                 FS_Print(file, builtinshaderstring);
1870                 FS_Close(file);
1871                 Con_Printf("glsl/default.glsl written\n");
1872         }
1873         else
1874                 Con_Printf("failed to write to glsl/default.glsl\n");
1875
1876         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1877         if (file)
1878         {
1879                 FS_Print(file, "/* The engine may define the following macros:\n");
1880                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1881                 for (i = 0;i < SHADERMODE_COUNT;i++)
1882                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1883                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1884                         FS_Print(file, shaderpermutationinfo[i].pretext);
1885                 FS_Print(file, "*/\n");
1886                 FS_Print(file, builtinhlslshaderstring);
1887                 FS_Close(file);
1888                 Con_Printf("hlsl/default.hlsl written\n");
1889         }
1890         else
1891                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1892 }
1893
1894 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1895 {
1896         if (!second)
1897                 texturemode = GL_MODULATE;
1898         switch (vid.renderpath)
1899         {
1900         case RENDERPATH_D3D9:
1901 #ifdef SUPPORTD3D
1902                 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))));
1903                 R_Mesh_TexBind(GL20TU_FIRST , first );
1904                 R_Mesh_TexBind(GL20TU_SECOND, second);
1905 #endif
1906                 break;
1907         case RENDERPATH_D3D10:
1908                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1909                 break;
1910         case RENDERPATH_D3D11:
1911                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1912                 break;
1913         case RENDERPATH_GL20:
1914         case RENDERPATH_GLES2:
1915                 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))));
1916                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1917                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1918                 break;
1919         case RENDERPATH_GL13:
1920                 R_Mesh_TexBind(0, first );
1921                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1922                 R_Mesh_TexBind(1, second);
1923                 if (second)
1924                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1925                 break;
1926         case RENDERPATH_GL11:
1927                 R_Mesh_TexBind(0, first );
1928                 break;
1929         case RENDERPATH_SOFT:
1930                 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))));
1931                 R_Mesh_TexBind(GL20TU_FIRST , first );
1932                 R_Mesh_TexBind(GL20TU_SECOND, second);
1933                 break;
1934         }
1935 }
1936
1937 void R_SetupShader_DepthOrShadow(void)
1938 {
1939         switch (vid.renderpath)
1940         {
1941         case RENDERPATH_D3D9:
1942 #ifdef SUPPORTD3D
1943                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1944 #endif
1945                 break;
1946         case RENDERPATH_D3D10:
1947                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1948                 break;
1949         case RENDERPATH_D3D11:
1950                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1951                 break;
1952         case RENDERPATH_GL20:
1953         case RENDERPATH_GLES2:
1954                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1955                 break;
1956         case RENDERPATH_GL13:
1957                 R_Mesh_TexBind(0, 0);
1958                 R_Mesh_TexBind(1, 0);
1959                 break;
1960         case RENDERPATH_GL11:
1961                 R_Mesh_TexBind(0, 0);
1962                 break;
1963         case RENDERPATH_SOFT:
1964                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1965                 break;
1966         }
1967 }
1968
1969 void R_SetupShader_ShowDepth(void)
1970 {
1971         switch (vid.renderpath)
1972         {
1973         case RENDERPATH_D3D9:
1974 #ifdef SUPPORTHLSL
1975                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1976 #endif
1977                 break;
1978         case RENDERPATH_D3D10:
1979                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1980                 break;
1981         case RENDERPATH_D3D11:
1982                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1983                 break;
1984         case RENDERPATH_GL20:
1985         case RENDERPATH_GLES2:
1986                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1987                 break;
1988         case RENDERPATH_GL13:
1989                 break;
1990         case RENDERPATH_GL11:
1991                 break;
1992         case RENDERPATH_SOFT:
1993                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1994                 break;
1995         }
1996 }
1997
1998 extern qboolean r_shadow_usingdeferredprepass;
1999 extern cvar_t r_shadow_deferred_8bitrange;
2000 extern rtexture_t *r_shadow_attenuationgradienttexture;
2001 extern rtexture_t *r_shadow_attenuation2dtexture;
2002 extern rtexture_t *r_shadow_attenuation3dtexture;
2003 extern qboolean r_shadow_usingshadowmap2d;
2004 extern qboolean r_shadow_usingshadowmaportho;
2005 extern float r_shadow_shadowmap_texturescale[2];
2006 extern float r_shadow_shadowmap_parameters[4];
2007 extern qboolean r_shadow_shadowmapvsdct;
2008 extern qboolean r_shadow_shadowmapsampler;
2009 extern int r_shadow_shadowmappcf;
2010 extern rtexture_t *r_shadow_shadowmap2dtexture;
2011 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2012 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2013 extern matrix4x4_t r_shadow_shadowmapmatrix;
2014 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2015 extern int r_shadow_prepass_width;
2016 extern int r_shadow_prepass_height;
2017 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2018 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2019 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2020 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2021 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2022
2023 #define BLENDFUNC_ALLOWS_COLORMOD      1
2024 #define BLENDFUNC_ALLOWS_FOG           2
2025 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2026 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2027 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2028 static int R_BlendFuncFlags(int src, int dst)
2029 {
2030         int r = 0;
2031
2032         // a blendfunc allows colormod if:
2033         // a) it can never keep the destination pixel invariant, or
2034         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2035         // this is to prevent unintended side effects from colormod
2036
2037         // a blendfunc allows fog if:
2038         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2039         // this is to prevent unintended side effects from fog
2040
2041         // these checks are the output of fogeval.pl
2042
2043         r |= BLENDFUNC_ALLOWS_COLORMOD;
2044         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2045         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2046         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2047         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2048         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2049         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2050         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2051         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2052         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2053         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2054         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2055         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2056         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2057         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2058         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2059         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2063         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2064         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2065
2066         return r;
2067 }
2068
2069 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)
2070 {
2071         // select a permutation of the lighting shader appropriate to this
2072         // combination of texture, entity, light source, and fogging, only use the
2073         // minimum features necessary to avoid wasting rendering time in the
2074         // fragment shader on features that are not being used
2075         unsigned int permutation = 0;
2076         unsigned int mode = 0;
2077         int blendfuncflags;
2078         static float dummy_colormod[3] = {1, 1, 1};
2079         float *colormod = rsurface.colormod;
2080         float m16f[16];
2081         matrix4x4_t tempmatrix;
2082         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2083         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2084                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2085         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2086                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2087         if (rsurfacepass == RSURFPASS_BACKGROUND)
2088         {
2089                 // distorted background
2090                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2091                 {
2092                         mode = SHADERMODE_WATER;
2093                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2094                         {
2095                                 // this is the right thing to do for wateralpha
2096                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2097                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2098                         }
2099                         else
2100                         {
2101                                 // this is the right thing to do for entity alpha
2102                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2103                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2104                         }
2105                 }
2106                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2107                 {
2108                         mode = SHADERMODE_REFRACTION;
2109                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2110                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2111                 }
2112                 else
2113                 {
2114                         mode = SHADERMODE_GENERIC;
2115                         permutation |= SHADERPERMUTATION_DIFFUSE;
2116                         GL_BlendFunc(GL_ONE, GL_ZERO);
2117                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2118                 }
2119         }
2120         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2121         {
2122                 if (r_glsl_offsetmapping.integer)
2123                 {
2124                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2125                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2126                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2127                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2128                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2129                         {
2130                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2131                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2132                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2133                         }
2134                 }
2135                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2136                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2137                 // normalmap (deferred prepass), may use alpha test on diffuse
2138                 mode = SHADERMODE_DEFERREDGEOMETRY;
2139                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2140                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2141                 GL_BlendFunc(GL_ONE, GL_ZERO);
2142                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2143         }
2144         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2145         {
2146                 if (r_glsl_offsetmapping.integer)
2147                 {
2148                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2149                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2150                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2151                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2152                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2153                         {
2154                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2155                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2156                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2157                         }
2158                 }
2159                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2160                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2161                 // light source
2162                 mode = SHADERMODE_LIGHTSOURCE;
2163                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2164                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2165                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2166                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2167                 if (diffusescale > 0)
2168                         permutation |= SHADERPERMUTATION_DIFFUSE;
2169                 if (specularscale > 0)
2170                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2171                 if (r_refdef.fogenabled)
2172                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2173                 if (rsurface.texture->colormapping)
2174                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2175                 if (r_shadow_usingshadowmap2d)
2176                 {
2177                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2178                         if(r_shadow_shadowmapvsdct)
2179                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2180
2181                         if (r_shadow_shadowmapsampler)
2182                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2183                         if (r_shadow_shadowmappcf > 1)
2184                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2185                         else if (r_shadow_shadowmappcf)
2186                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2187                 }
2188                 if (rsurface.texture->reflectmasktexture)
2189                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2190                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2191                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2192         }
2193         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2194         {
2195                 if (r_glsl_offsetmapping.integer)
2196                 {
2197                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2198                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2199                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2200                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2201                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2202                         {
2203                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2204                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2205                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2206                         }
2207                 }
2208                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2209                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2210                 // unshaded geometry (fullbright or ambient model lighting)
2211                 mode = SHADERMODE_FLATCOLOR;
2212                 ambientscale = diffusescale = specularscale = 0;
2213                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2214                         permutation |= SHADERPERMUTATION_GLOW;
2215                 if (r_refdef.fogenabled)
2216                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2217                 if (rsurface.texture->colormapping)
2218                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2219                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2220                 {
2221                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2222                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2223
2224                         if (r_shadow_shadowmapsampler)
2225                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2226                         if (r_shadow_shadowmappcf > 1)
2227                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2228                         else if (r_shadow_shadowmappcf)
2229                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2230                 }
2231                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2232                         permutation |= SHADERPERMUTATION_REFLECTION;
2233                 if (rsurface.texture->reflectmasktexture)
2234                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2235                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2236                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2237         }
2238         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2239         {
2240                 if (r_glsl_offsetmapping.integer)
2241                 {
2242                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2243                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2244                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2245                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2246                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2247                         {
2248                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2249                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2250                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2251                         }
2252                 }
2253                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2254                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2255                 // directional model lighting
2256                 mode = SHADERMODE_LIGHTDIRECTION;
2257                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258                         permutation |= SHADERPERMUTATION_GLOW;
2259                 permutation |= SHADERPERMUTATION_DIFFUSE;
2260                 if (specularscale > 0)
2261                         permutation |= SHADERPERMUTATION_SPECULAR;
2262                 if (r_refdef.fogenabled)
2263                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2264                 if (rsurface.texture->colormapping)
2265                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2266                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2267                 {
2268                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2269                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2270
2271                         if (r_shadow_shadowmapsampler)
2272                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2273                         if (r_shadow_shadowmappcf > 1)
2274                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2275                         else if (r_shadow_shadowmappcf)
2276                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2277                 }
2278                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2279                         permutation |= SHADERPERMUTATION_REFLECTION;
2280                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2281                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2282                 if (rsurface.texture->reflectmasktexture)
2283                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2284                 if (r_shadow_bouncegridtexture)
2285                 {
2286                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2287                         if (r_shadow_bouncegriddirectional)
2288                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2289                 }
2290                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2291                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2292         }
2293         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2294         {
2295                 if (r_glsl_offsetmapping.integer)
2296                 {
2297                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2298                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2299                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2300                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2301                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2302                         {
2303                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2304                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2305                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2306                         }
2307                 }
2308                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2309                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2310                 // ambient model lighting
2311                 mode = SHADERMODE_LIGHTDIRECTION;
2312                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2313                         permutation |= SHADERPERMUTATION_GLOW;
2314                 if (r_refdef.fogenabled)
2315                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2316                 if (rsurface.texture->colormapping)
2317                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2318                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2319                 {
2320                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2321                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2322
2323                         if (r_shadow_shadowmapsampler)
2324                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2325                         if (r_shadow_shadowmappcf > 1)
2326                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2327                         else if (r_shadow_shadowmappcf)
2328                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2329                 }
2330                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2331                         permutation |= SHADERPERMUTATION_REFLECTION;
2332                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2333                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2334                 if (rsurface.texture->reflectmasktexture)
2335                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2336                 if (r_shadow_bouncegridtexture)
2337                 {
2338                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2339                         if (r_shadow_bouncegriddirectional)
2340                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2341                 }
2342                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2343                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2344         }
2345         else
2346         {
2347                 if (r_glsl_offsetmapping.integer)
2348                 {
2349                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2350                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2351                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2352                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2353                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2354                         {
2355                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2356                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2357                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2358                         }
2359                 }
2360                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2361                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2362                 // lightmapped wall
2363                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2364                         permutation |= SHADERPERMUTATION_GLOW;
2365                 if (r_refdef.fogenabled)
2366                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2367                 if (rsurface.texture->colormapping)
2368                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2369                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2370                 {
2371                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2372                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2373
2374                         if (r_shadow_shadowmapsampler)
2375                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2376                         if (r_shadow_shadowmappcf > 1)
2377                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2378                         else if (r_shadow_shadowmappcf)
2379                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2380                 }
2381                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2382                         permutation |= SHADERPERMUTATION_REFLECTION;
2383                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2384                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2385                 if (rsurface.texture->reflectmasktexture)
2386                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2387                 if (FAKELIGHT_ENABLED)
2388                 {
2389                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2390                         mode = SHADERMODE_FAKELIGHT;
2391                         permutation |= SHADERPERMUTATION_DIFFUSE;
2392                         if (specularscale > 0)
2393                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2394                 }
2395                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2396                 {
2397                         // deluxemapping (light direction texture)
2398                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2399                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2400                         else
2401                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2402                         permutation |= SHADERPERMUTATION_DIFFUSE;
2403                         if (specularscale > 0)
2404                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2405                 }
2406                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2407                 {
2408                         // fake deluxemapping (uniform light direction in tangentspace)
2409                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2410                         permutation |= SHADERPERMUTATION_DIFFUSE;
2411                         if (specularscale > 0)
2412                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2413                 }
2414                 else if (rsurface.uselightmaptexture)
2415                 {
2416                         // ordinary lightmapping (q1bsp, q3bsp)
2417                         mode = SHADERMODE_LIGHTMAP;
2418                 }
2419                 else
2420                 {
2421                         // ordinary vertex coloring (q3bsp)
2422                         mode = SHADERMODE_VERTEXCOLOR;
2423                 }
2424                 if (r_shadow_bouncegridtexture)
2425                 {
2426                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2427                         if (r_shadow_bouncegriddirectional)
2428                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2429                 }
2430                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2431                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2432         }
2433         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2434                 colormod = dummy_colormod;
2435         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2436                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2437         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2438                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2439         switch(vid.renderpath)
2440         {
2441         case RENDERPATH_D3D9:
2442 #ifdef SUPPORTD3D
2443                 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);
2444                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2445                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2446                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2447                 if (mode == SHADERMODE_LIGHTSOURCE)
2448                 {
2449                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2450                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2451                 }
2452                 else
2453                 {
2454                         if (mode == SHADERMODE_LIGHTDIRECTION)
2455                         {
2456                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2457                         }
2458                 }
2459                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2460                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2461                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2462                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2463                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2464
2465                 if (mode == SHADERMODE_LIGHTSOURCE)
2466                 {
2467                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2468                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2469                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2470                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2471                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2472
2473                         // additive passes are only darkened by fog, not tinted
2474                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2475                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2476                 }
2477                 else
2478                 {
2479                         if (mode == SHADERMODE_FLATCOLOR)
2480                         {
2481                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2482                         }
2483                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2484                         {
2485                                 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]);
2486                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2487                                 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);
2488                                 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);
2489                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2490                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2491                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2492                         }
2493                         else
2494                         {
2495                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2496                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2497                                 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);
2498                                 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);
2499                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2500                         }
2501                         // additive passes are only darkened by fog, not tinted
2502                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2503                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2504                         else
2505                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2506                         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);
2507                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2508                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2509                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2510                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2511                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2512                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2513                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2514                         if (mode == SHADERMODE_WATER)
2515                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2516                 }
2517                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2518                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2519                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2520                 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));
2521                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2522                 if (rsurface.texture->pantstexture)
2523                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2524                 else
2525                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2526                 if (rsurface.texture->shirttexture)
2527                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2528                 else
2529                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2530                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2531                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2532                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2533                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2534                 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));
2535                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2536                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2537
2538                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2539                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2540                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2541                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2542                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2543                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2544                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2545                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2546                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2547                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2548                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2549                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2550                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2551                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2552                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2553                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2554                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2555                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2556                 {
2557                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2558                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2559                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2560                 }
2561                 else
2562                 {
2563                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2564                 }
2565 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2566 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2567                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2568                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2569                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2570                 {
2571                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2572                         if (rsurface.rtlight)
2573                         {
2574                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2575                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2576                         }
2577                 }
2578 #endif
2579                 break;
2580         case RENDERPATH_D3D10:
2581                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2582                 break;
2583         case RENDERPATH_D3D11:
2584                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2585                 break;
2586         case RENDERPATH_GL20:
2587         case RENDERPATH_GLES2:
2588                 if (!vid.useinterleavedarrays)
2589                 {
2590                         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);
2591                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2592                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2593                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2594                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2595                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2596                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2597                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2598                 }
2599                 else
2600                 {
2601                         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);
2602                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2603                 }
2604                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2605                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2606                 if (mode == SHADERMODE_LIGHTSOURCE)
2607                 {
2608                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2609                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2610                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2611                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2612                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2613                         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);
2614         
2615                         // additive passes are only darkened by fog, not tinted
2616                         if (r_glsl_permutation->loc_FogColor >= 0)
2617                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2618                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2619                 }
2620                 else
2621                 {
2622                         if (mode == SHADERMODE_FLATCOLOR)
2623                         {
2624                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2625                         }
2626                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2627                         {
2628                                 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]);
2629                                 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]);
2630                                 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);
2631                                 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);
2632                                 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);
2633                                 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]);
2634                                 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]);
2635                         }
2636                         else
2637                         {
2638                                 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]);
2639                                 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]);
2640                                 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);
2641                                 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);
2642                                 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);
2643                         }
2644                         // additive passes are only darkened by fog, not tinted
2645                         if (r_glsl_permutation->loc_FogColor >= 0)
2646                         {
2647                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2648                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2649                                 else
2650                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2651                         }
2652                         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);
2653                         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]);
2654                         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]);
2655                         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]);
2656                         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]);
2657                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2658                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2659                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2660                         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]);
2661                 }
2662                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2663                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2664                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2665                 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]);
2666                 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]);
2667
2668                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2669                 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));
2670                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2671                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2672                 {
2673                         if (rsurface.texture->pantstexture)
2674                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2675                         else
2676                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2677                 }
2678                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2679                 {
2680                         if (rsurface.texture->shirttexture)
2681                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2682                         else
2683                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2684                 }
2685                 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]);
2686                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2687                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2688                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2689                 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));
2690                 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]);
2691                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2692                 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);}
2693                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2694
2695                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2696                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2697                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2698                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2699                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2700                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2701                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2702                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2703                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2704                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2705                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2706                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2707                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2708                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2709                 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);
2710                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2711                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2712                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2713                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2714                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2715                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2716                 {
2717                         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);
2718                         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);
2719                         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);
2720                 }
2721                 else
2722                 {
2723                         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);
2724                 }
2725                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2726                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2727                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2728                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2729                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2730                 {
2731                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2732                         if (rsurface.rtlight)
2733                         {
2734                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2735                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2736                         }
2737                 }
2738                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2739                 CHECKGLERROR
2740                 break;
2741         case RENDERPATH_GL13:
2742         case RENDERPATH_GL11:
2743                 break;
2744         case RENDERPATH_SOFT:
2745                 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);
2746                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2747                 R_SetupShader_SetPermutationSoft(mode, permutation);
2748                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2749                 if (mode == SHADERMODE_LIGHTSOURCE)
2750                 {
2751                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2752                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2753                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2754                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2755                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2756                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2757         
2758                         // additive passes are only darkened by fog, not tinted
2759                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2760                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2761                 }
2762                 else
2763                 {
2764                         if (mode == SHADERMODE_FLATCOLOR)
2765                         {
2766                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2767                         }
2768                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2769                         {
2770                                 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]);
2771                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2772                                 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);
2773                                 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);
2774                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2775                                 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]);
2776                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2777                         }
2778                         else
2779                         {
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2782                                 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);
2783                                 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);
2784                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2785                         }
2786                         // additive passes are only darkened by fog, not tinted
2787                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2788                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2789                         else
2790                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2791                         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);
2792                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2793                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2794                         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]);
2795                         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]);
2796                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2797                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2798                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2799                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2800                 }
2801                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2802                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2803                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2804                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2805                 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]);
2806
2807                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2808                 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));
2809                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2810                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2811                 {
2812                         if (rsurface.texture->pantstexture)
2813                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2814                         else
2815                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2816                 }
2817                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2818                 {
2819                         if (rsurface.texture->shirttexture)
2820                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2821                         else
2822                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2823                 }
2824                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2825                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2826                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2827                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2828                 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));
2829                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2830                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2831
2832                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2833                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2834                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2835                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2836                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2837                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2838                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2839                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2840                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2841                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2842                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2843                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2844                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2845                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2846                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2847                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2848                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2849                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2850                 {
2851                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2852                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2853                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2854                 }
2855                 else
2856                 {
2857                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2858                 }
2859 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2860 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2861                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2862                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2863                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2864                 {
2865                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2866                         if (rsurface.rtlight)
2867                         {
2868                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2869                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2870                         }
2871                 }
2872                 break;
2873         }
2874 }
2875
2876 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2877 {
2878         // select a permutation of the lighting shader appropriate to this
2879         // combination of texture, entity, light source, and fogging, only use the
2880         // minimum features necessary to avoid wasting rendering time in the
2881         // fragment shader on features that are not being used
2882         unsigned int permutation = 0;
2883         unsigned int mode = 0;
2884         const float *lightcolorbase = rtlight->currentcolor;
2885         float ambientscale = rtlight->ambientscale;
2886         float diffusescale = rtlight->diffusescale;
2887         float specularscale = rtlight->specularscale;
2888         // this is the location of the light in view space
2889         vec3_t viewlightorigin;
2890         // this transforms from view space (camera) to light space (cubemap)
2891         matrix4x4_t viewtolight;
2892         matrix4x4_t lighttoview;
2893         float viewtolight16f[16];
2894         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2895         // light source
2896         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2897         if (rtlight->currentcubemap != r_texture_whitecube)
2898                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2899         if (diffusescale > 0)
2900                 permutation |= SHADERPERMUTATION_DIFFUSE;
2901         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2902                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2903         if (r_shadow_usingshadowmap2d)
2904         {
2905                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2906                 if (r_shadow_shadowmapvsdct)
2907                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2908
2909                 if (r_shadow_shadowmapsampler)
2910                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2911                 if (r_shadow_shadowmappcf > 1)
2912                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2913                 else if (r_shadow_shadowmappcf)
2914                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2915         }
2916         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2917         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2918         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2919         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2920         switch(vid.renderpath)
2921         {
2922         case RENDERPATH_D3D9:
2923 #ifdef SUPPORTD3D
2924                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2925                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2926                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2927                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2928                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2929                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2930                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2931                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2932                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2933                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2934                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2935
2936                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2937                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2938                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2939                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2940                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2941                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2942 #endif
2943                 break;
2944         case RENDERPATH_D3D10:
2945                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2946                 break;
2947         case RENDERPATH_D3D11:
2948                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2949                 break;
2950         case RENDERPATH_GL20:
2951         case RENDERPATH_GLES2:
2952                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2953                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2954                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2955                 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);
2956                 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);
2957                 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);
2958                 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]);
2959                 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]);
2960                 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));
2961                 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]);
2962                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2963
2964                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2965                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2966                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2967                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2968                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2969                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2970                 break;
2971         case RENDERPATH_GL13:
2972         case RENDERPATH_GL11:
2973                 break;
2974         case RENDERPATH_SOFT:
2975                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2976                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2977                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2978                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2979                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2980                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2981                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2982                 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]);
2983                 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));
2984                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2985                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2986
2987                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2988                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2989                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2990                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2991                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2992                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2993                 break;
2994         }
2995 }
2996
2997 #define SKINFRAME_HASH 1024
2998
2999 typedef struct
3000 {
3001         int loadsequence; // incremented each level change
3002         memexpandablearray_t array;
3003         skinframe_t *hash[SKINFRAME_HASH];
3004 }
3005 r_skinframe_t;
3006 r_skinframe_t r_skinframe;
3007
3008 void R_SkinFrame_PrepareForPurge(void)
3009 {
3010         r_skinframe.loadsequence++;
3011         // wrap it without hitting zero
3012         if (r_skinframe.loadsequence >= 200)
3013                 r_skinframe.loadsequence = 1;
3014 }
3015
3016 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3017 {
3018         if (!skinframe)
3019                 return;
3020         // mark the skinframe as used for the purging code
3021         skinframe->loadsequence = r_skinframe.loadsequence;
3022 }
3023
3024 void R_SkinFrame_Purge(void)
3025 {
3026         int i;
3027         skinframe_t *s;
3028         for (i = 0;i < SKINFRAME_HASH;i++)
3029         {
3030                 for (s = r_skinframe.hash[i];s;s = s->next)
3031                 {
3032                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3033                         {
3034                                 if (s->merged == s->base)
3035                                         s->merged = NULL;
3036                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3037                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3038                                 R_PurgeTexture(s->merged);s->merged = NULL;
3039                                 R_PurgeTexture(s->base  );s->base   = NULL;
3040                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3041                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3042                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3043                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3044                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3045                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3046                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3047                                 s->loadsequence = 0;
3048                         }
3049                 }
3050         }
3051 }
3052
3053 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3054         skinframe_t *item;
3055         char basename[MAX_QPATH];
3056
3057         Image_StripImageExtension(name, basename, sizeof(basename));
3058
3059         if( last == NULL ) {
3060                 int hashindex;
3061                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3062                 item = r_skinframe.hash[hashindex];
3063         } else {
3064                 item = last->next;
3065         }
3066
3067         // linearly search through the hash bucket
3068         for( ; item ; item = item->next ) {
3069                 if( !strcmp( item->basename, basename ) ) {
3070                         return item;
3071                 }
3072         }
3073         return NULL;
3074 }
3075
3076 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3077 {
3078         skinframe_t *item;
3079         int hashindex;
3080         char basename[MAX_QPATH];
3081
3082         Image_StripImageExtension(name, basename, sizeof(basename));
3083
3084         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3085         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3086                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3087                         break;
3088
3089         if (!item) {
3090                 rtexture_t *dyntexture;
3091                 // check whether its a dynamic texture
3092                 dyntexture = CL_GetDynTexture( basename );
3093                 if (!add && !dyntexture)
3094                         return NULL;
3095                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3096                 memset(item, 0, sizeof(*item));
3097                 strlcpy(item->basename, basename, sizeof(item->basename));
3098                 item->base = dyntexture; // either NULL or dyntexture handle
3099                 item->textureflags = textureflags;
3100                 item->comparewidth = comparewidth;
3101                 item->compareheight = compareheight;
3102                 item->comparecrc = comparecrc;
3103                 item->next = r_skinframe.hash[hashindex];
3104                 r_skinframe.hash[hashindex] = item;
3105         }
3106         else if( item->base == NULL )
3107         {
3108                 rtexture_t *dyntexture;
3109                 // check whether its a dynamic texture
3110                 // 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]
3111                 dyntexture = CL_GetDynTexture( basename );
3112                 item->base = dyntexture; // either NULL or dyntexture handle
3113         }
3114
3115         R_SkinFrame_MarkUsed(item);
3116         return item;
3117 }
3118
3119 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3120         { \
3121                 unsigned long long avgcolor[5], wsum; \
3122                 int pix, comp, w; \
3123                 avgcolor[0] = 0; \
3124                 avgcolor[1] = 0; \
3125                 avgcolor[2] = 0; \
3126                 avgcolor[3] = 0; \
3127                 avgcolor[4] = 0; \
3128                 wsum = 0; \
3129                 for(pix = 0; pix < cnt; ++pix) \
3130                 { \
3131                         w = 0; \
3132                         for(comp = 0; comp < 3; ++comp) \
3133                                 w += getpixel; \
3134                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3135                         { \
3136                                 ++wsum; \
3137                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3138                                 w = getpixel; \
3139                                 for(comp = 0; comp < 3; ++comp) \
3140                                         avgcolor[comp] += getpixel * w; \
3141                                 avgcolor[3] += w; \
3142                         } \
3143                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3144                         avgcolor[4] += getpixel; \
3145                 } \
3146                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3147                         avgcolor[3] = 1; \
3148                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3149                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3150                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3151                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3152         }
3153
3154 extern cvar_t gl_picmip;
3155 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3156 {
3157         int j;
3158         unsigned char *pixels;
3159         unsigned char *bumppixels;
3160         unsigned char *basepixels = NULL;
3161         int basepixels_width = 0;
3162         int basepixels_height = 0;
3163         skinframe_t *skinframe;
3164         rtexture_t *ddsbase = NULL;
3165         qboolean ddshasalpha = false;
3166         float ddsavgcolor[4];
3167         char basename[MAX_QPATH];
3168         int miplevel = R_PicmipForFlags(textureflags);
3169         int savemiplevel = miplevel;
3170         int mymiplevel;
3171
3172         if (cls.state == ca_dedicated)
3173                 return NULL;
3174
3175         // return an existing skinframe if already loaded
3176         // if loading of the first image fails, don't make a new skinframe as it
3177         // would cause all future lookups of this to be missing
3178         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3179         if (skinframe && skinframe->base)
3180                 return skinframe;
3181
3182         Image_StripImageExtension(name, basename, sizeof(basename));
3183
3184         // check for DDS texture file first
3185         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3186         {
3187                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3188                 if (basepixels == NULL)
3189                         return NULL;
3190         }
3191
3192         // FIXME handle miplevel
3193
3194         if (developer_loading.integer)
3195                 Con_Printf("loading skin \"%s\"\n", name);
3196
3197         // we've got some pixels to store, so really allocate this new texture now
3198         if (!skinframe)
3199                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3200         skinframe->stain = NULL;
3201         skinframe->merged = NULL;
3202         skinframe->base = NULL;
3203         skinframe->pants = NULL;
3204         skinframe->shirt = NULL;
3205         skinframe->nmap = NULL;
3206         skinframe->gloss = NULL;
3207         skinframe->glow = NULL;
3208         skinframe->fog = NULL;
3209         skinframe->reflect = NULL;
3210         skinframe->hasalpha = false;
3211
3212         if (ddsbase)
3213         {
3214                 skinframe->base = ddsbase;
3215                 skinframe->hasalpha = ddshasalpha;
3216                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3217                 if (r_loadfog && skinframe->hasalpha)
3218                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3219                 //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]);
3220         }
3221         else
3222         {
3223                 basepixels_width = image_width;
3224                 basepixels_height = image_height;
3225                 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);
3226                 if (textureflags & TEXF_ALPHA)
3227                 {
3228                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3229                         {
3230                                 if (basepixels[j] < 255)
3231                                 {
3232                                         skinframe->hasalpha = true;
3233                                         break;
3234                                 }
3235                         }
3236                         if (r_loadfog && skinframe->hasalpha)
3237                         {
3238                                 // has transparent pixels
3239                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3240                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3241                                 {
3242                                         pixels[j+0] = 255;
3243                                         pixels[j+1] = 255;
3244                                         pixels[j+2] = 255;
3245                                         pixels[j+3] = basepixels[j+3];
3246                                 }
3247                                 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);
3248                                 Mem_Free(pixels);
3249                         }
3250                 }
3251                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3252                 //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]);
3253                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3254                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3255                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3256                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3257         }
3258
3259         if (r_loaddds)
3260         {
3261                 mymiplevel = savemiplevel;
3262                 if (r_loadnormalmap)
3263                         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);
3264                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3265                 if (r_loadgloss)
3266                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3267                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3268                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3269                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3270         }
3271
3272         // _norm is the name used by tenebrae and has been adopted as standard
3273         if (r_loadnormalmap && skinframe->nmap == NULL)
3274         {
3275                 mymiplevel = savemiplevel;
3276                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3277                 {
3278                         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);
3279                         Mem_Free(pixels);
3280                         pixels = NULL;
3281                 }
3282                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3283                 {
3284                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3285                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3286                         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);
3287                         Mem_Free(pixels);
3288                         Mem_Free(bumppixels);
3289                 }
3290                 else if (r_shadow_bumpscale_basetexture.value > 0)
3291                 {
3292                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3293                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3294                         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);
3295                         Mem_Free(pixels);
3296                 }
3297                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3298                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3299         }
3300
3301         // _luma is supported only for tenebrae compatibility
3302         // _glow is the preferred name
3303         mymiplevel = savemiplevel;
3304         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))))
3305         {
3306                 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);
3307                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3308                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3309                 Mem_Free(pixels);pixels = NULL;
3310         }
3311
3312         mymiplevel = savemiplevel;
3313         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3314         {
3315                 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);
3316                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3317                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3318                 Mem_Free(pixels);
3319                 pixels = NULL;
3320         }
3321
3322         mymiplevel = savemiplevel;
3323         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3324         {
3325                 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);
3326                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3327                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3328                 Mem_Free(pixels);
3329                 pixels = NULL;
3330         }
3331
3332         mymiplevel = savemiplevel;
3333         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3334         {
3335                 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);
3336                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3337                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3338                 Mem_Free(pixels);
3339                 pixels = NULL;
3340         }
3341
3342         mymiplevel = savemiplevel;
3343         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3344         {
3345                 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);
3346                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3347                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3348                 Mem_Free(pixels);
3349                 pixels = NULL;
3350         }
3351
3352         if (basepixels)
3353                 Mem_Free(basepixels);
3354
3355         return skinframe;
3356 }
3357
3358 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3359 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3360 {
3361         int i;
3362         unsigned char *temp1, *temp2;
3363         skinframe_t *skinframe;
3364
3365         if (cls.state == ca_dedicated)
3366                 return NULL;
3367
3368         // if already loaded just return it, otherwise make a new skinframe
3369         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3370         if (skinframe && skinframe->base)
3371                 return skinframe;
3372
3373         skinframe->stain = NULL;
3374         skinframe->merged = NULL;
3375         skinframe->base = NULL;
3376         skinframe->pants = NULL;
3377         skinframe->shirt = NULL;
3378         skinframe->nmap = NULL;
3379         skinframe->gloss = NULL;
3380         skinframe->glow = NULL;
3381         skinframe->fog = NULL;
3382         skinframe->reflect = NULL;
3383         skinframe->hasalpha = false;
3384
3385         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3386         if (!skindata)
3387                 return NULL;
3388
3389         if (developer_loading.integer)
3390                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3391
3392         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3393         {
3394                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3395                 temp2 = temp1 + width * height * 4;
3396                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3397                 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);
3398                 Mem_Free(temp1);
3399         }
3400         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3401         if (textureflags & TEXF_ALPHA)
3402         {
3403                 for (i = 3;i < width * height * 4;i += 4)
3404                 {
3405                         if (skindata[i] < 255)
3406                         {
3407                                 skinframe->hasalpha = true;
3408                                 break;
3409                         }
3410                 }
3411                 if (r_loadfog && skinframe->hasalpha)
3412                 {
3413                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3414                         memcpy(fogpixels, skindata, width * height * 4);
3415                         for (i = 0;i < width * height * 4;i += 4)
3416                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3417                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3418                         Mem_Free(fogpixels);
3419                 }
3420         }
3421
3422         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3423         //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]);
3424
3425         return skinframe;
3426 }
3427
3428 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3429 {
3430         int i;
3431         int featuresmask;
3432         skinframe_t *skinframe;
3433
3434         if (cls.state == ca_dedicated)
3435                 return NULL;
3436
3437         // if already loaded just return it, otherwise make a new skinframe
3438         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3439         if (skinframe && skinframe->base)
3440                 return skinframe;
3441
3442         skinframe->stain = NULL;
3443         skinframe->merged = NULL;
3444         skinframe->base = NULL;
3445         skinframe->pants = NULL;
3446         skinframe->shirt = NULL;
3447         skinframe->nmap = NULL;
3448         skinframe->gloss = NULL;
3449         skinframe->glow = NULL;
3450         skinframe->fog = NULL;
3451         skinframe->reflect = NULL;
3452         skinframe->hasalpha = false;
3453
3454         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3455         if (!skindata)
3456                 return NULL;
3457
3458         if (developer_loading.integer)
3459                 Con_Printf("loading quake skin \"%s\"\n", name);
3460
3461         // 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)
3462         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3463         memcpy(skinframe->qpixels, skindata, width*height);
3464         skinframe->qwidth = width;
3465         skinframe->qheight = height;
3466
3467         featuresmask = 0;
3468         for (i = 0;i < width * height;i++)
3469                 featuresmask |= palette_featureflags[skindata[i]];
3470
3471         skinframe->hasalpha = false;
3472         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3473         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3474         skinframe->qgeneratemerged = true;
3475         skinframe->qgeneratebase = skinframe->qhascolormapping;
3476         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3477
3478         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3479         //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]);
3480
3481         return skinframe;
3482 }
3483
3484 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3485 {
3486         int width;
3487         int height;
3488         unsigned char *skindata;
3489
3490         if (!skinframe->qpixels)
3491                 return;
3492
3493         if (!skinframe->qhascolormapping)
3494                 colormapped = false;
3495
3496         if (colormapped)
3497         {
3498                 if (!skinframe->qgeneratebase)
3499                         return;
3500         }
3501         else
3502         {
3503                 if (!skinframe->qgeneratemerged)
3504                         return;
3505         }
3506
3507         width = skinframe->qwidth;
3508         height = skinframe->qheight;
3509         skindata = skinframe->qpixels;
3510
3511         if (skinframe->qgeneratenmap)
3512         {
3513                 unsigned char *temp1, *temp2;
3514                 skinframe->qgeneratenmap = false;
3515                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3516                 temp2 = temp1 + width * height * 4;
3517                 // use either a custom palette or the quake palette
3518                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3519                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3520                 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);
3521                 Mem_Free(temp1);
3522         }
3523
3524         if (skinframe->qgenerateglow)
3525         {
3526                 skinframe->qgenerateglow = false;
3527                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3528         }
3529
3530         if (colormapped)
3531         {
3532                 skinframe->qgeneratebase = false;
3533                 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);
3534                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3535                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3536         }
3537         else
3538         {
3539                 skinframe->qgeneratemerged = false;
3540                 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);
3541         }
3542
3543         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3544         {
3545                 Mem_Free(skinframe->qpixels);
3546                 skinframe->qpixels = NULL;
3547         }
3548 }
3549
3550 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)
3551 {
3552         int i;
3553         skinframe_t *skinframe;
3554
3555         if (cls.state == ca_dedicated)
3556                 return NULL;
3557
3558         // if already loaded just return it, otherwise make a new skinframe
3559         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3560         if (skinframe && skinframe->base)
3561                 return skinframe;
3562
3563         skinframe->stain = NULL;
3564         skinframe->merged = NULL;
3565         skinframe->base = NULL;
3566         skinframe->pants = NULL;
3567         skinframe->shirt = NULL;
3568         skinframe->nmap = NULL;
3569         skinframe->gloss = NULL;
3570         skinframe->glow = NULL;
3571         skinframe->fog = NULL;
3572         skinframe->reflect = NULL;
3573         skinframe->hasalpha = false;
3574
3575         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3576         if (!skindata)
3577                 return NULL;
3578
3579         if (developer_loading.integer)
3580                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3581
3582         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3583         if (textureflags & TEXF_ALPHA)
3584         {
3585                 for (i = 0;i < width * height;i++)
3586                 {
3587                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3588                         {
3589                                 skinframe->hasalpha = true;
3590                                 break;
3591                         }
3592                 }
3593                 if (r_loadfog && skinframe->hasalpha)
3594                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3595         }
3596
3597         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3598         //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]);
3599
3600         return skinframe;
3601 }
3602
3603 skinframe_t *R_SkinFrame_LoadMissing(void)
3604 {
3605         skinframe_t *skinframe;
3606
3607         if (cls.state == ca_dedicated)
3608                 return NULL;
3609
3610         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3611         skinframe->stain = NULL;
3612         skinframe->merged = NULL;
3613         skinframe->base = NULL;
3614         skinframe->pants = NULL;
3615         skinframe->shirt = NULL;
3616         skinframe->nmap = NULL;
3617         skinframe->gloss = NULL;
3618         skinframe->glow = NULL;
3619         skinframe->fog = NULL;
3620         skinframe->reflect = NULL;
3621         skinframe->hasalpha = false;
3622
3623         skinframe->avgcolor[0] = rand() / RAND_MAX;
3624         skinframe->avgcolor[1] = rand() / RAND_MAX;
3625         skinframe->avgcolor[2] = rand() / RAND_MAX;
3626         skinframe->avgcolor[3] = 1;
3627
3628         return skinframe;
3629 }
3630
3631 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3632 typedef struct suffixinfo_s
3633 {
3634         const char *suffix;
3635         qboolean flipx, flipy, flipdiagonal;
3636 }
3637 suffixinfo_t;
3638 static suffixinfo_t suffix[3][6] =
3639 {
3640         {
3641                 {"px",   false, false, false},
3642                 {"nx",   false, false, false},
3643                 {"py",   false, false, false},
3644                 {"ny",   false, false, false},
3645                 {"pz",   false, false, false},
3646                 {"nz",   false, false, false}
3647         },
3648         {
3649                 {"posx", false, false, false},
3650                 {"negx", false, false, false},
3651                 {"posy", false, false, false},
3652                 {"negy", false, false, false},
3653                 {"posz", false, false, false},
3654                 {"negz", false, false, false}
3655         },
3656         {
3657                 {"rt",    true, false,  true},
3658                 {"lf",   false,  true,  true},
3659                 {"ft",    true,  true, false},
3660                 {"bk",   false, false, false},
3661                 {"up",    true, false,  true},
3662                 {"dn",    true, false,  true}
3663         }
3664 };
3665
3666 static int componentorder[4] = {0, 1, 2, 3};
3667
3668 rtexture_t *R_LoadCubemap(const char *basename)
3669 {
3670         int i, j, cubemapsize;
3671         unsigned char *cubemappixels, *image_buffer;
3672         rtexture_t *cubemaptexture;
3673         char name[256];
3674         // must start 0 so the first loadimagepixels has no requested width/height
3675         cubemapsize = 0;
3676         cubemappixels = NULL;
3677         cubemaptexture = NULL;
3678         // keep trying different suffix groups (posx, px, rt) until one loads
3679         for (j = 0;j < 3 && !cubemappixels;j++)
3680         {
3681                 // load the 6 images in the suffix group
3682                 for (i = 0;i < 6;i++)
3683                 {
3684                         // generate an image name based on the base and and suffix
3685                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3686                         // load it
3687                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3688                         {
3689                                 // an image loaded, make sure width and height are equal
3690                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3691                                 {
3692                                         // if this is the first image to load successfully, allocate the cubemap memory
3693                                         if (!cubemappixels && image_width >= 1)
3694                                         {
3695                                                 cubemapsize = image_width;
3696                                                 // note this clears to black, so unavailable sides are black
3697                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3698                                         }
3699                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3700                                         if (cubemappixels)
3701                                                 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);
3702                                 }
3703                                 else
3704                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3705                                 // free the image
3706                                 Mem_Free(image_buffer);
3707                         }
3708                 }
3709         }
3710         // if a cubemap loaded, upload it
3711         if (cubemappixels)
3712         {
3713                 if (developer_loading.integer)
3714                         Con_Printf("loading cubemap \"%s\"\n", basename);
3715
3716                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3717                 Mem_Free(cubemappixels);
3718         }
3719         else
3720         {
3721                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3722                 if (developer_loading.integer)
3723                 {
3724                         Con_Printf("(tried tried images ");
3725                         for (j = 0;j < 3;j++)
3726                                 for (i = 0;i < 6;i++)
3727                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3728                         Con_Print(" and was unable to find any of them).\n");
3729                 }
3730         }
3731         return cubemaptexture;
3732 }
3733
3734 rtexture_t *R_GetCubemap(const char *basename)
3735 {
3736         int i;
3737         for (i = 0;i < r_texture_numcubemaps;i++)
3738                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3739                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3740         if (i >= MAX_CUBEMAPS)
3741                 return r_texture_whitecube;
3742         r_texture_numcubemaps++;
3743         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3744         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3745         return r_texture_cubemaps[i].texture;
3746 }
3747
3748 void R_FreeCubemaps(void)
3749 {
3750         int i;
3751         for (i = 0;i < r_texture_numcubemaps;i++)
3752         {
3753                 if (developer_loading.integer)
3754                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3755                 if (r_texture_cubemaps[i].texture)
3756                         R_FreeTexture(r_texture_cubemaps[i].texture);
3757         }
3758         r_texture_numcubemaps = 0;
3759 }
3760
3761 void R_Main_FreeViewCache(void)
3762 {
3763         if (r_refdef.viewcache.entityvisible)
3764                 Mem_Free(r_refdef.viewcache.entityvisible);
3765         if (r_refdef.viewcache.world_pvsbits)
3766                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3767         if (r_refdef.viewcache.world_leafvisible)
3768                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3769         if (r_refdef.viewcache.world_surfacevisible)
3770                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3771         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3772 }
3773
3774 void R_Main_ResizeViewCache(void)
3775 {
3776         int numentities = r_refdef.scene.numentities;
3777         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3778         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3779         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3780         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3781         if (r_refdef.viewcache.maxentities < numentities)
3782         {
3783                 r_refdef.viewcache.maxentities = numentities;
3784                 if (r_refdef.viewcache.entityvisible)
3785                         Mem_Free(r_refdef.viewcache.entityvisible);
3786                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3787         }
3788         if (r_refdef.viewcache.world_numclusters != numclusters)
3789         {
3790                 r_refdef.viewcache.world_numclusters = numclusters;
3791                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3792                 if (r_refdef.viewcache.world_pvsbits)
3793                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3794                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3795         }
3796         if (r_refdef.viewcache.world_numleafs != numleafs)
3797         {
3798                 r_refdef.viewcache.world_numleafs = numleafs;
3799                 if (r_refdef.viewcache.world_leafvisible)
3800                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3801                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3802         }
3803         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3804         {
3805                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3806                 if (r_refdef.viewcache.world_surfacevisible)
3807                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3808                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3809         }
3810 }
3811
3812 extern rtexture_t *loadingscreentexture;
3813 void gl_main_start(void)
3814 {
3815         loadingscreentexture = NULL;
3816         r_texture_blanknormalmap = NULL;
3817         r_texture_white = NULL;
3818         r_texture_grey128 = NULL;
3819         r_texture_black = NULL;
3820         r_texture_whitecube = NULL;
3821         r_texture_normalizationcube = NULL;
3822         r_texture_fogattenuation = NULL;
3823         r_texture_fogheighttexture = NULL;
3824         r_texture_gammaramps = NULL;
3825         r_texture_numcubemaps = 0;
3826
3827         r_loaddds = r_texture_dds_load.integer != 0;
3828         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3829
3830         switch(vid.renderpath)
3831         {
3832         case RENDERPATH_GL20:
3833         case RENDERPATH_D3D9:
3834         case RENDERPATH_D3D10:
3835         case RENDERPATH_D3D11:
3836         case RENDERPATH_SOFT:
3837         case RENDERPATH_GLES2:
3838                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3839                 Cvar_SetValueQuick(&gl_combine, 1);
3840                 Cvar_SetValueQuick(&r_glsl, 1);
3841                 r_loadnormalmap = true;
3842                 r_loadgloss = true;
3843                 r_loadfog = false;
3844                 break;
3845         case RENDERPATH_GL13:
3846                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3847                 Cvar_SetValueQuick(&gl_combine, 1);
3848                 Cvar_SetValueQuick(&r_glsl, 0);
3849                 r_loadnormalmap = false;
3850                 r_loadgloss = false;
3851                 r_loadfog = true;
3852                 break;
3853         case RENDERPATH_GL11:
3854                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3855                 Cvar_SetValueQuick(&gl_combine, 0);
3856                 Cvar_SetValueQuick(&r_glsl, 0);
3857                 r_loadnormalmap = false;
3858                 r_loadgloss = false;
3859                 r_loadfog = true;
3860                 break;
3861         }
3862
3863         R_AnimCache_Free();
3864         R_FrameData_Reset();
3865
3866         r_numqueries = 0;
3867         r_maxqueries = 0;
3868         memset(r_queries, 0, sizeof(r_queries));
3869
3870         r_qwskincache = NULL;
3871         r_qwskincache_size = 0;
3872
3873         // due to caching of texture_t references, the collision cache must be reset
3874         Collision_Cache_Reset(true);
3875
3876         // set up r_skinframe loading system for textures
3877         memset(&r_skinframe, 0, sizeof(r_skinframe));
3878         r_skinframe.loadsequence = 1;
3879         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3880
3881         r_main_texturepool = R_AllocTexturePool();
3882         R_BuildBlankTextures();
3883         R_BuildNoTexture();
3884         if (vid.support.arb_texture_cube_map)
3885         {
3886                 R_BuildWhiteCube();
3887                 R_BuildNormalizationCube();
3888         }
3889         r_texture_fogattenuation = NULL;
3890         r_texture_fogheighttexture = NULL;
3891         r_texture_gammaramps = NULL;
3892         //r_texture_fogintensity = NULL;
3893         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3894         memset(&r_waterstate, 0, sizeof(r_waterstate));
3895         r_glsl_permutation = NULL;
3896         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3897         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3898         glslshaderstring = NULL;
3899 #ifdef SUPPORTD3D
3900         r_hlsl_permutation = NULL;
3901         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3902         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3903 #endif
3904         hlslshaderstring = NULL;
3905         memset(&r_svbsp, 0, sizeof (r_svbsp));
3906
3907         r_refdef.fogmasktable_density = 0;
3908 }
3909
3910 void gl_main_shutdown(void)
3911 {
3912         R_AnimCache_Free();
3913         R_FrameData_Reset();
3914
3915         R_Main_FreeViewCache();
3916
3917         switch(vid.renderpath)
3918         {
3919         case RENDERPATH_GL11:
3920         case RENDERPATH_GL13:
3921         case RENDERPATH_GL20:
3922         case RENDERPATH_GLES2:
3923                 if (r_maxqueries)
3924                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3925                 break;
3926         case RENDERPATH_D3D9:
3927                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3928                 break;
3929         case RENDERPATH_D3D10:
3930                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3931                 break;
3932         case RENDERPATH_D3D11:
3933                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3934                 break;
3935         case RENDERPATH_SOFT:
3936                 break;
3937         }
3938
3939         r_numqueries = 0;
3940         r_maxqueries = 0;
3941         memset(r_queries, 0, sizeof(r_queries));
3942
3943         r_qwskincache = NULL;
3944         r_qwskincache_size = 0;
3945
3946         // clear out the r_skinframe state
3947         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3948         memset(&r_skinframe, 0, sizeof(r_skinframe));
3949
3950         if (r_svbsp.nodes)
3951                 Mem_Free(r_svbsp.nodes);
3952         memset(&r_svbsp, 0, sizeof (r_svbsp));
3953         R_FreeTexturePool(&r_main_texturepool);
3954         loadingscreentexture = NULL;
3955         r_texture_blanknormalmap = NULL;
3956         r_texture_white = NULL;
3957         r_texture_grey128 = NULL;
3958         r_texture_black = NULL;
3959         r_texture_whitecube = NULL;
3960         r_texture_normalizationcube = NULL;
3961         r_texture_fogattenuation = NULL;
3962         r_texture_fogheighttexture = NULL;
3963         r_texture_gammaramps = NULL;
3964         r_texture_numcubemaps = 0;
3965         //r_texture_fogintensity = NULL;
3966         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3967         memset(&r_waterstate, 0, sizeof(r_waterstate));
3968         R_GLSL_Restart_f();
3969
3970         r_glsl_permutation = NULL;
3971         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3972         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3973         glslshaderstring = NULL;
3974 #ifdef SUPPORTD3D
3975         r_hlsl_permutation = NULL;
3976         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3977         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3978 #endif
3979         hlslshaderstring = NULL;
3980 }
3981
3982 extern void CL_ParseEntityLump(char *entitystring);
3983 void gl_main_newmap(void)
3984 {
3985         // FIXME: move this code to client
3986         char *entities, entname[MAX_QPATH];
3987         if (r_qwskincache)
3988                 Mem_Free(r_qwskincache);
3989         r_qwskincache = NULL;
3990         r_qwskincache_size = 0;
3991         if (cl.worldmodel)
3992         {
3993                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3994                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3995                 {
3996                         CL_ParseEntityLump(entities);
3997                         Mem_Free(entities);
3998                         return;
3999                 }
4000                 if (cl.worldmodel->brush.entities)
4001                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4002         }
4003         R_Main_FreeViewCache();
4004
4005         R_FrameData_Reset();
4006 }
4007
4008 void GL_Main_Init(void)
4009 {
4010         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4011
4012         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4013         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4014         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4015         if (gamemode == GAME_NEHAHRA)
4016         {
4017                 Cvar_RegisterVariable (&gl_fogenable);
4018                 Cvar_RegisterVariable (&gl_fogdensity);
4019                 Cvar_RegisterVariable (&gl_fogred);
4020                 Cvar_RegisterVariable (&gl_foggreen);
4021                 Cvar_RegisterVariable (&gl_fogblue);
4022                 Cvar_RegisterVariable (&gl_fogstart);
4023                 Cvar_RegisterVariable (&gl_fogend);
4024                 Cvar_RegisterVariable (&gl_skyclip);
4025         }
4026         Cvar_RegisterVariable(&r_motionblur);
4027         Cvar_RegisterVariable(&r_motionblur_maxblur);
4028         Cvar_RegisterVariable(&r_motionblur_bmin);
4029         Cvar_RegisterVariable(&r_motionblur_vmin);
4030         Cvar_RegisterVariable(&r_motionblur_vmax);
4031         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4032         Cvar_RegisterVariable(&r_motionblur_randomize);
4033         Cvar_RegisterVariable(&r_damageblur);
4034         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4035         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4036         Cvar_RegisterVariable(&r_equalize_entities_by);
4037         Cvar_RegisterVariable(&r_equalize_entities_to);
4038         Cvar_RegisterVariable(&r_depthfirst);
4039         Cvar_RegisterVariable(&r_useinfinitefarclip);
4040         Cvar_RegisterVariable(&r_farclip_base);
4041         Cvar_RegisterVariable(&r_farclip_world);
4042         Cvar_RegisterVariable(&r_nearclip);
4043         Cvar_RegisterVariable(&r_showbboxes);
4044         Cvar_RegisterVariable(&r_showsurfaces);
4045         Cvar_RegisterVariable(&r_showtris);
4046         Cvar_RegisterVariable(&r_shownormals);
4047         Cvar_RegisterVariable(&r_showlighting);
4048         Cvar_RegisterVariable(&r_showshadowvolumes);
4049         Cvar_RegisterVariable(&r_showcollisionbrushes);
4050         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4051         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4052         Cvar_RegisterVariable(&r_showdisabledepthtest);
4053         Cvar_RegisterVariable(&r_drawportals);
4054         Cvar_RegisterVariable(&r_drawentities);
4055         Cvar_RegisterVariable(&r_draw2d);
4056         Cvar_RegisterVariable(&r_drawworld);
4057         Cvar_RegisterVariable(&r_cullentities_trace);
4058         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4059         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4060         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4061         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4062         Cvar_RegisterVariable(&r_drawviewmodel);
4063         Cvar_RegisterVariable(&r_drawexteriormodel);
4064         Cvar_RegisterVariable(&r_speeds);
4065         Cvar_RegisterVariable(&r_fullbrights);
4066         Cvar_RegisterVariable(&r_wateralpha);
4067         Cvar_RegisterVariable(&r_dynamic);
4068         Cvar_RegisterVariable(&r_fakelight);
4069         Cvar_RegisterVariable(&r_fakelight_intensity);
4070         Cvar_RegisterVariable(&r_fullbright);
4071         Cvar_RegisterVariable(&r_shadows);
4072         Cvar_RegisterVariable(&r_shadows_darken);
4073         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4074         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4075         Cvar_RegisterVariable(&r_shadows_throwdistance);
4076         Cvar_RegisterVariable(&r_shadows_throwdirection);
4077         Cvar_RegisterVariable(&r_shadows_focus);
4078         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4079         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4080         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4081         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4082         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4083         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4084         Cvar_RegisterVariable(&r_fog_exp2);
4085         Cvar_RegisterVariable(&r_fog_clear);
4086         Cvar_RegisterVariable(&r_drawfog);
4087         Cvar_RegisterVariable(&r_transparentdepthmasking);
4088         Cvar_RegisterVariable(&r_texture_dds_load);
4089         Cvar_RegisterVariable(&r_texture_dds_save);
4090         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4091         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4092         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4093         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4094         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4095         Cvar_RegisterVariable(&r_textureunits);
4096         Cvar_RegisterVariable(&gl_combine);
4097         Cvar_RegisterVariable(&r_viewfbo);
4098         Cvar_RegisterVariable(&r_viewscale);
4099         Cvar_RegisterVariable(&r_glsl);
4100         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4101         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4102         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4103         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4104         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4105         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4106         Cvar_RegisterVariable(&r_glsl_postprocess);
4107         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4108         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4109         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4110         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4111         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4112         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4113         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4114         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4115
4116         Cvar_RegisterVariable(&r_water);
4117         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4118         Cvar_RegisterVariable(&r_water_clippingplanebias);
4119         Cvar_RegisterVariable(&r_water_refractdistort);
4120         Cvar_RegisterVariable(&r_water_reflectdistort);
4121         Cvar_RegisterVariable(&r_water_scissormode);
4122         Cvar_RegisterVariable(&r_lerpsprites);
4123         Cvar_RegisterVariable(&r_lerpmodels);
4124         Cvar_RegisterVariable(&r_lerplightstyles);
4125         Cvar_RegisterVariable(&r_waterscroll);
4126         Cvar_RegisterVariable(&r_bloom);
4127         Cvar_RegisterVariable(&r_bloom_colorscale);
4128         Cvar_RegisterVariable(&r_bloom_brighten);
4129         Cvar_RegisterVariable(&r_bloom_blur);
4130         Cvar_RegisterVariable(&r_bloom_resolution);
4131         Cvar_RegisterVariable(&r_bloom_colorexponent);
4132         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4133         Cvar_RegisterVariable(&r_hdr);
4134         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4135         Cvar_RegisterVariable(&r_hdr_glowintensity);
4136         Cvar_RegisterVariable(&r_hdr_range);
4137         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4138         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4139         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4140         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4141         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4142         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4143         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4144         Cvar_RegisterVariable(&developer_texturelogging);
4145         Cvar_RegisterVariable(&gl_lightmaps);
4146         Cvar_RegisterVariable(&r_test);
4147         Cvar_RegisterVariable(&r_glsl_saturation);
4148         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4149         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4150         Cvar_RegisterVariable(&r_framedatasize);
4151         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4152                 Cvar_SetValue("r_fullbrights", 0);
4153         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4154
4155         Cvar_RegisterVariable(&r_track_sprites);
4156         Cvar_RegisterVariable(&r_track_sprites_flags);
4157         Cvar_RegisterVariable(&r_track_sprites_scalew);
4158         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4159         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4160         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4161         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4162         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4163 }
4164
4165 extern void R_Textures_Init(void);
4166 extern void GL_Draw_Init(void);
4167 extern void GL_Main_Init(void);
4168 extern void R_Shadow_Init(void);
4169 extern void R_Sky_Init(void);
4170 extern void GL_Surf_Init(void);
4171 extern void R_Particles_Init(void);
4172 extern void R_Explosion_Init(void);
4173 extern void gl_backend_init(void);
4174 extern void Sbar_Init(void);
4175 extern void R_LightningBeams_Init(void);
4176 extern void Mod_RenderInit(void);
4177 extern void Font_Init(void);
4178
4179 void Render_Init(void)
4180 {
4181         gl_backend_init();
4182         R_Textures_Init();
4183         GL_Main_Init();
4184         Font_Init();
4185         GL_Draw_Init();
4186         R_Shadow_Init();
4187         R_Sky_Init();
4188         GL_Surf_Init();
4189         Sbar_Init();
4190         R_Particles_Init();
4191         R_Explosion_Init();
4192         R_LightningBeams_Init();
4193         Mod_RenderInit();
4194 }
4195
4196 /*
4197 ===============
4198 GL_Init
4199 ===============
4200 */
4201 extern char *ENGINE_EXTENSIONS;
4202 void GL_Init (void)
4203 {
4204         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4205         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4206         gl_version = (const char *)qglGetString(GL_VERSION);
4207         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4208
4209         if (!gl_extensions)
4210                 gl_extensions = "";
4211         if (!gl_platformextensions)
4212                 gl_platformextensions = "";
4213
4214         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4215         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4216         Con_Printf("GL_VERSION: %s\n", gl_version);
4217         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4218         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4219
4220         VID_CheckExtensions();
4221
4222         // LordHavoc: report supported extensions
4223         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4224
4225         // clear to black (loading plaque will be seen over this)
4226         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4227 }
4228
4229 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4230 {
4231         int i;
4232         mplane_t *p;
4233         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4234         {
4235                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4236                 if (i == 4)
4237                         continue;
4238                 p = r_refdef.view.frustum + i;
4239                 switch(p->signbits)
4240                 {
4241                 default:
4242                 case 0:
4243                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4244                                 return true;
4245                         break;
4246                 case 1:
4247                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4248                                 return true;
4249                         break;
4250                 case 2:
4251                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4252                                 return true;
4253                         break;
4254                 case 3:
4255                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4256                                 return true;
4257                         break;
4258                 case 4:
4259                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4260                                 return true;
4261                         break;
4262                 case 5:
4263                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4264                                 return true;
4265                         break;
4266                 case 6:
4267                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4268                                 return true;
4269                         break;
4270                 case 7:
4271                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4272                                 return true;
4273                         break;
4274                 }
4275         }
4276         return false;
4277 }
4278
4279 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4280 {
4281         int i;
4282         const mplane_t *p;
4283         for (i = 0;i < numplanes;i++)
4284         {
4285                 p = planes + i;
4286                 switch(p->signbits)
4287                 {
4288                 default:
4289                 case 0:
4290                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4291                                 return true;
4292                         break;
4293                 case 1:
4294                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4295                                 return true;
4296                         break;
4297                 case 2:
4298                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4299                                 return true;
4300                         break;
4301                 case 3:
4302                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4303                                 return true;
4304                         break;
4305                 case 4:
4306                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4307                                 return true;
4308                         break;
4309                 case 5:
4310                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4311                                 return true;
4312                         break;
4313                 case 6:
4314                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4315                                 return true;
4316                         break;
4317                 case 7:
4318                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4319                                 return true;
4320                         break;
4321                 }
4322         }
4323         return false;
4324 }
4325
4326 //==================================================================================
4327
4328 // LordHavoc: this stores temporary data used within the same frame
4329
4330 typedef struct r_framedata_mem_s
4331 {
4332         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4333         size_t size; // how much usable space
4334         size_t current; // how much space in use
4335         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4336         size_t wantedsize; // how much space was allocated
4337         unsigned char *data; // start of real data (16byte aligned)
4338 }
4339 r_framedata_mem_t;
4340
4341 static r_framedata_mem_t *r_framedata_mem;
4342
4343 void R_FrameData_Reset(void)
4344 {
4345         while (r_framedata_mem)
4346         {
4347                 r_framedata_mem_t *next = r_framedata_mem->purge;
4348                 Mem_Free(r_framedata_mem);
4349                 r_framedata_mem = next;
4350         }
4351 }
4352
4353 void R_FrameData_Resize(void)
4354 {
4355         size_t wantedsize;
4356         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4357         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4358         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4359         {
4360                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4361                 newmem->wantedsize = wantedsize;
4362                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4363                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4364                 newmem->current = 0;
4365                 newmem->mark = 0;
4366                 newmem->purge = r_framedata_mem;
4367                 r_framedata_mem = newmem;
4368         }
4369 }
4370
4371 void R_FrameData_NewFrame(void)
4372 {
4373         R_FrameData_Resize();
4374         if (!r_framedata_mem)
4375                 return;
4376         // if we ran out of space on the last frame, free the old memory now
4377         while (r_framedata_mem->purge)
4378         {
4379                 // repeatedly remove the second item in the list, leaving only head
4380                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4381                 Mem_Free(r_framedata_mem->purge);
4382                 r_framedata_mem->purge = next;
4383         }
4384         // reset the current mem pointer
4385         r_framedata_mem->current = 0;
4386         r_framedata_mem->mark = 0;
4387 }
4388
4389 void *R_FrameData_Alloc(size_t size)
4390 {
4391         void *data;
4392
4393         // align to 16 byte boundary - the data pointer is already aligned, so we
4394         // only need to ensure the size of every allocation is also aligned
4395         size = (size + 15) & ~15;
4396
4397         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4398         {
4399                 // emergency - we ran out of space, allocate more memory
4400                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4401                 R_FrameData_Resize();
4402         }
4403
4404         data = r_framedata_mem->data + r_framedata_mem->current;
4405         r_framedata_mem->current += size;
4406
4407         // count the usage for stats
4408         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4409         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4410
4411         return (void *)data;
4412 }
4413
4414 void *R_FrameData_Store(size_t size, void *data)
4415 {
4416         void *d = R_FrameData_Alloc(size);
4417         if (d && data)
4418                 memcpy(d, data, size);
4419         return d;
4420 }
4421
4422 void R_FrameData_SetMark(void)
4423 {
4424         if (!r_framedata_mem)
4425                 return;
4426         r_framedata_mem->mark = r_framedata_mem->current;
4427 }
4428
4429 void R_FrameData_ReturnToMark(void)
4430 {
4431         if (!r_framedata_mem)
4432                 return;
4433         r_framedata_mem->current = r_framedata_mem->mark;
4434 }
4435
4436 //==================================================================================
4437
4438 // LordHavoc: animcache originally written by Echon, rewritten since then
4439
4440 /**
4441  * Animation cache prevents re-generating mesh data for an animated model
4442  * multiple times in one frame for lighting, shadowing, reflections, etc.
4443  */
4444
4445 void R_AnimCache_Free(void)
4446 {
4447 }
4448
4449 void R_AnimCache_ClearCache(void)
4450 {
4451         int i;
4452         entity_render_t *ent;
4453
4454         for (i = 0;i < r_refdef.scene.numentities;i++)
4455         {
4456                 ent = r_refdef.scene.entities[i];
4457                 ent->animcache_vertex3f = NULL;
4458                 ent->animcache_normal3f = NULL;
4459                 ent->animcache_svector3f = NULL;
4460                 ent->animcache_tvector3f = NULL;
4461                 ent->animcache_vertexmesh = NULL;
4462                 ent->animcache_vertex3fbuffer = NULL;
4463                 ent->animcache_vertexmeshbuffer = NULL;
4464         }
4465 }
4466
4467 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4468 {
4469         int i;
4470
4471         // check if we need the meshbuffers
4472         if (!vid.useinterleavedarrays)
4473                 return;
4474
4475         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4476                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4477         // TODO: upload vertex3f buffer?
4478         if (ent->animcache_vertexmesh)
4479         {
4480                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4481                 for (i = 0;i < numvertices;i++)
4482                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4483                 if (ent->animcache_svector3f)
4484                         for (i = 0;i < numvertices;i++)
4485                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4486                 if (ent->animcache_tvector3f)
4487                         for (i = 0;i < numvertices;i++)
4488                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4489                 if (ent->animcache_normal3f)
4490                         for (i = 0;i < numvertices;i++)
4491                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4492                 // TODO: upload vertexmeshbuffer?
4493         }
4494 }
4495
4496 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4497 {
4498         dp_model_t *model = ent->model;
4499         int numvertices;
4500         // see if it's already cached this frame
4501         if (ent->animcache_vertex3f)
4502         {
4503                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4504                 if (wantnormals || wanttangents)
4505                 {
4506                         if (ent->animcache_normal3f)
4507                                 wantnormals = false;
4508                         if (ent->animcache_svector3f)
4509                                 wanttangents = false;
4510                         if (wantnormals || wanttangents)
4511                         {
4512                                 numvertices = model->surfmesh.num_vertices;
4513                                 if (wantnormals)
4514                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4515                                 if (wanttangents)
4516                                 {
4517                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4518                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4519                                 }
4520                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4521                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4522                         }
4523                 }
4524         }
4525         else
4526         {
4527                 // see if this ent is worth caching
4528                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4529                         return false;
4530                 // get some memory for this entity and generate mesh data
4531                 numvertices = model->surfmesh.num_vertices;
4532                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4533                 if (wantnormals)
4534                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4535                 if (wanttangents)
4536                 {
4537                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4538                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4539                 }
4540                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4541                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4542         }
4543         return true;
4544 }
4545
4546 void R_AnimCache_CacheVisibleEntities(void)
4547 {
4548         int i;
4549         qboolean wantnormals = true;
4550         qboolean wanttangents = !r_showsurfaces.integer;
4551
4552         switch(vid.renderpath)
4553         {
4554         case RENDERPATH_GL20:
4555         case RENDERPATH_D3D9:
4556         case RENDERPATH_D3D10:
4557         case RENDERPATH_D3D11:
4558         case RENDERPATH_GLES2:
4559                 break;
4560         case RENDERPATH_GL13:
4561         case RENDERPATH_GL11:
4562                 wanttangents = false;
4563                 break;
4564         case RENDERPATH_SOFT:
4565                 break;
4566         }
4567
4568         if (r_shownormals.integer)
4569                 wanttangents = wantnormals = true;
4570
4571         // TODO: thread this
4572         // NOTE: R_PrepareRTLights() also caches entities
4573
4574         for (i = 0;i < r_refdef.scene.numentities;i++)
4575                 if (r_refdef.viewcache.entityvisible[i])
4576                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4577 }
4578
4579 //==================================================================================
4580
4581 static void R_View_UpdateEntityLighting (void)
4582 {
4583         int i;
4584         entity_render_t *ent;
4585         vec3_t tempdiffusenormal, avg;
4586         vec_t f, fa, fd, fdd;
4587         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4588
4589         for (i = 0;i < r_refdef.scene.numentities;i++)
4590         {
4591                 ent = r_refdef.scene.entities[i];
4592
4593                 // skip unseen models
4594                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4595                         continue;
4596
4597                 // skip bsp models
4598                 if (ent->model && ent->model->brush.num_leafs)
4599                 {
4600                         // TODO: use modellight for r_ambient settings on world?
4601                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4602                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4603                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4604                         continue;
4605                 }
4606
4607                 // fetch the lighting from the worldmodel data
4608                 VectorClear(ent->modellight_ambient);
4609                 VectorClear(ent->modellight_diffuse);
4610                 VectorClear(tempdiffusenormal);
4611                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4612                 {
4613                         vec3_t org;
4614                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4615
4616                         // complete lightning for lit sprites
4617                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4618                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4619                         {
4620                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4621                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4622                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4623                         }
4624                         else
4625                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4626
4627                         if(ent->flags & RENDER_EQUALIZE)
4628                         {
4629                                 // first fix up ambient lighting...
4630                                 if(r_equalize_entities_minambient.value > 0)
4631                                 {
4632                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4633                                         if(fd > 0)
4634                                         {
4635                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4636                                                 if(fa < r_equalize_entities_minambient.value * fd)
4637                                                 {
4638                                                         // solve:
4639                                                         //   fa'/fd' = minambient
4640                                                         //   fa'+0.25*fd' = fa+0.25*fd
4641                                                         //   ...
4642                                                         //   fa' = fd' * minambient
4643                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4644                                                         //   ...
4645                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4646                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4647                                                         //   ...
4648                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4649                                                         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
4650                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4651                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4652                                                 }
4653                                         }
4654                                 }
4655
4656                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4657                                 {
4658                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4659                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4660                                         f = fa + 0.25 * fd;
4661                                         if(f > 0)
4662                                         {
4663                                                 // adjust brightness and saturation to target
4664                                                 avg[0] = avg[1] = avg[2] = fa / f;
4665                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4666                                                 avg[0] = avg[1] = avg[2] = fd / f;
4667                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4668                                         }
4669                                 }
4670                         }
4671                 }
4672                 else // highly rare
4673                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4674
4675                 // move the light direction into modelspace coordinates for lighting code
4676                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4677                 if(VectorLength2(ent->modellight_lightdir) == 0)
4678                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4679                 VectorNormalize(ent->modellight_lightdir);
4680         }
4681 }
4682
4683 #define MAX_LINEOFSIGHTTRACES 64
4684
4685 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4686 {
4687         int i;
4688         vec3_t boxmins, boxmaxs;
4689         vec3_t start;
4690         vec3_t end;
4691         dp_model_t *model = r_refdef.scene.worldmodel;
4692
4693         if (!model || !model->brush.TraceLineOfSight)
4694                 return true;
4695
4696         // expand the box a little
4697         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4698         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4699         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4700         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4701         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4702         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4703
4704         // return true if eye is inside enlarged box
4705         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4706                 return true;
4707
4708         // try center
4709         VectorCopy(eye, start);
4710         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4711         if (model->brush.TraceLineOfSight(model, start, end))
4712                 return true;
4713
4714         // try various random positions
4715         for (i = 0;i < numsamples;i++)
4716         {
4717                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4718                 if (model->brush.TraceLineOfSight(model, start, end))
4719                         return true;
4720         }
4721
4722         return false;
4723 }
4724
4725
4726 static void R_View_UpdateEntityVisible (void)
4727 {
4728         int i;
4729         int renderimask;
4730         int samples;
4731         entity_render_t *ent;
4732
4733         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4734                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4735                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4736                 :                                                          RENDER_EXTERIORMODEL;
4737         if (!r_drawviewmodel.integer)
4738                 renderimask |= RENDER_VIEWMODEL;
4739         if (!r_drawexteriormodel.integer)
4740                 renderimask |= RENDER_EXTERIORMODEL;
4741         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4742         {
4743                 // worldmodel can check visibility
4744                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4745                 for (i = 0;i < r_refdef.scene.numentities;i++)
4746                 {
4747                         ent = r_refdef.scene.entities[i];
4748                         if (!(ent->flags & renderimask))
4749                         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)))
4750                         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))
4751                                 r_refdef.viewcache.entityvisible[i] = true;
4752                 }
4753                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4754                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4755                 {
4756                         for (i = 0;i < r_refdef.scene.numentities;i++)
4757                         {
4758                                 ent = r_refdef.scene.entities[i];
4759                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4760                                 {
4761                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4762                                         if (samples < 0)
4763                                                 continue; // temp entities do pvs only
4764                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4765                                                 ent->last_trace_visibility = realtime;
4766                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4767                                                 r_refdef.viewcache.entityvisible[i] = 0;
4768                                 }
4769                         }
4770                 }
4771         }
4772         else
4773         {
4774                 // no worldmodel or it can't check visibility
4775                 for (i = 0;i < r_refdef.scene.numentities;i++)
4776                 {
4777                         ent = r_refdef.scene.entities[i];
4778                         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));
4779                 }
4780         }
4781 }
4782
4783 /// only used if skyrendermasked, and normally returns false
4784 int R_DrawBrushModelsSky (void)
4785 {
4786         int i, sky;
4787         entity_render_t *ent;
4788
4789         sky = false;
4790         for (i = 0;i < r_refdef.scene.numentities;i++)
4791         {
4792                 if (!r_refdef.viewcache.entityvisible[i])
4793                         continue;
4794                 ent = r_refdef.scene.entities[i];
4795                 if (!ent->model || !ent->model->DrawSky)
4796                         continue;
4797                 ent->model->DrawSky(ent);
4798                 sky = true;
4799         }
4800         return sky;
4801 }
4802
4803 static void R_DrawNoModel(entity_render_t *ent);
4804 static void R_DrawModels(void)
4805 {
4806         int i;
4807         entity_render_t *ent;
4808
4809         for (i = 0;i < r_refdef.scene.numentities;i++)
4810         {
4811                 if (!r_refdef.viewcache.entityvisible[i])
4812                         continue;
4813                 ent = r_refdef.scene.entities[i];
4814                 r_refdef.stats.entities++;
4815                 if (ent->model && ent->model->Draw != NULL)
4816                         ent->model->Draw(ent);
4817                 else
4818                         R_DrawNoModel(ent);
4819         }
4820 }
4821
4822 static void R_DrawModelsDepth(void)
4823 {
4824         int i;
4825         entity_render_t *ent;
4826
4827         for (i = 0;i < r_refdef.scene.numentities;i++)
4828         {
4829                 if (!r_refdef.viewcache.entityvisible[i])
4830                         continue;
4831                 ent = r_refdef.scene.entities[i];
4832                 if (ent->model && ent->model->DrawDepth != NULL)
4833                         ent->model->DrawDepth(ent);
4834         }
4835 }
4836
4837 static void R_DrawModelsDebug(void)
4838 {
4839         int i;
4840         entity_render_t *ent;
4841
4842         for (i = 0;i < r_refdef.scene.numentities;i++)
4843         {
4844                 if (!r_refdef.viewcache.entityvisible[i])
4845                         continue;
4846                 ent = r_refdef.scene.entities[i];
4847                 if (ent->model && ent->model->DrawDebug != NULL)
4848                         ent->model->DrawDebug(ent);
4849         }
4850 }
4851
4852 static void R_DrawModelsAddWaterPlanes(void)
4853 {
4854         int i;
4855         entity_render_t *ent;
4856
4857         for (i = 0;i < r_refdef.scene.numentities;i++)
4858         {
4859                 if (!r_refdef.viewcache.entityvisible[i])
4860                         continue;
4861                 ent = r_refdef.scene.entities[i];
4862                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4863                         ent->model->DrawAddWaterPlanes(ent);
4864         }
4865 }
4866
4867 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4868 {
4869         if (r_hdr_irisadaptation.integer)
4870         {
4871                 vec3_t ambient;
4872                 vec3_t diffuse;
4873                 vec3_t diffusenormal;
4874                 vec_t brightness;
4875                 vec_t goal;
4876                 vec_t adjust;
4877                 vec_t current;
4878                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4879                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4880                 brightness = max(0.0000001f, brightness);
4881                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4882                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4883                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4884                 current = r_hdr_irisadaptation_value.value;
4885                 if (current < goal)
4886                         current = min(current + adjust, goal);
4887                 else if (current > goal)
4888                         current = max(current - adjust, goal);
4889                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4890                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4891         }
4892         else if (r_hdr_irisadaptation_value.value != 1.0f)
4893                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4894 }
4895
4896 static void R_View_SetFrustum(const int *scissor)
4897 {
4898         int i;
4899         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4900         vec3_t forward, left, up, origin, v;
4901
4902         if(scissor)
4903         {
4904                 // flipped x coordinates (because x points left here)
4905                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4906                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4907
4908                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4909                 switch(vid.renderpath)
4910                 {
4911                         case RENDERPATH_D3D9:
4912                         case RENDERPATH_D3D10:
4913                         case RENDERPATH_D3D11:
4914                                 // non-flipped y coordinates
4915                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4916                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4917                                 break;
4918                         case RENDERPATH_SOFT:
4919                         case RENDERPATH_GL11:
4920                         case RENDERPATH_GL13:
4921                         case RENDERPATH_GL20:
4922                         case RENDERPATH_GLES2:
4923                                 // non-flipped y coordinates
4924                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4925                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4926                                 break;
4927                 }
4928         }
4929
4930         // we can't trust r_refdef.view.forward and friends in reflected scenes
4931         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4932
4933 #if 0
4934         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4935         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4936         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4937         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4938         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4939         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4940         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4941         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4942         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4943         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4944         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4945         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4946 #endif
4947
4948 #if 0
4949         zNear = r_refdef.nearclip;
4950         nudge = 1.0 - 1.0 / (1<<23);
4951         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4952         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4953         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4954         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4955         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4956         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4957         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4958         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4959 #endif
4960
4961
4962
4963 #if 0
4964         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4965         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4966         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4967         r_refdef.view.frustum[0].dist = m[15] - m[12];
4968
4969         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4970         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4971         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4972         r_refdef.view.frustum[1].dist = m[15] + m[12];
4973
4974         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4975         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4976         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4977         r_refdef.view.frustum[2].dist = m[15] - m[13];
4978
4979         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4980         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4981         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4982         r_refdef.view.frustum[3].dist = m[15] + m[13];
4983
4984         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4985         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4986         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4987         r_refdef.view.frustum[4].dist = m[15] - m[14];
4988
4989         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4990         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4991         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4992         r_refdef.view.frustum[5].dist = m[15] + m[14];
4993 #endif
4994
4995         if (r_refdef.view.useperspective)
4996         {
4997                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4998                 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]);
4999                 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]);
5000                 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]);
5001                 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]);
5002
5003                 // then the normals from the corners relative to origin
5004                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5005                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5006                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5007                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5008
5009                 // in a NORMAL view, forward cross left == up
5010                 // in a REFLECTED view, forward cross left == down
5011                 // so our cross products above need to be adjusted for a left handed coordinate system
5012                 CrossProduct(forward, left, v);
5013                 if(DotProduct(v, up) < 0)
5014                 {
5015                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5016                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5017                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5018                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5019                 }
5020
5021                 // Leaving those out was a mistake, those were in the old code, and they
5022                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5023                 // I couldn't reproduce it after adding those normalizations. --blub
5024                 VectorNormalize(r_refdef.view.frustum[0].normal);
5025                 VectorNormalize(r_refdef.view.frustum[1].normal);
5026                 VectorNormalize(r_refdef.view.frustum[2].normal);
5027                 VectorNormalize(r_refdef.view.frustum[3].normal);
5028
5029                 // make the corners absolute
5030                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5031                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5032                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5033                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5034
5035                 // one more normal
5036                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5037
5038                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5039                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5040                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5041                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5042                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5043         }
5044         else
5045         {
5046                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5047                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5048                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5049                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5050                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5051                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5052                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5053                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5054                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5055                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5056         }
5057         r_refdef.view.numfrustumplanes = 5;
5058
5059         if (r_refdef.view.useclipplane)
5060         {
5061                 r_refdef.view.numfrustumplanes = 6;
5062                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5063         }
5064
5065         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5066                 PlaneClassify(r_refdef.view.frustum + i);
5067
5068         // LordHavoc: note to all quake engine coders, Quake had a special case
5069         // for 90 degrees which assumed a square view (wrong), so I removed it,
5070         // Quake2 has it disabled as well.
5071
5072         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5073         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5074         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5075         //PlaneClassify(&frustum[0]);
5076
5077         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5078         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5079         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5080         //PlaneClassify(&frustum[1]);
5081
5082         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5083         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5084         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5085         //PlaneClassify(&frustum[2]);
5086
5087         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5088         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5089         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5090         //PlaneClassify(&frustum[3]);
5091
5092         // nearclip plane
5093         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5094         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5095         //PlaneClassify(&frustum[4]);
5096 }
5097
5098 void R_View_UpdateWithScissor(const int *myscissor)
5099 {
5100         R_Main_ResizeViewCache();
5101         R_View_SetFrustum(myscissor);
5102         R_View_WorldVisibility(r_refdef.view.useclipplane);
5103         R_View_UpdateEntityVisible();
5104         R_View_UpdateEntityLighting();
5105 }
5106
5107 void R_View_Update(void)
5108 {
5109         R_Main_ResizeViewCache();
5110         R_View_SetFrustum(NULL);
5111         R_View_WorldVisibility(r_refdef.view.useclipplane);
5112         R_View_UpdateEntityVisible();
5113         R_View_UpdateEntityLighting();
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         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5129         {
5130                 // LordHavoc: couldn't figure out how to make this approach the
5131                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5132                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5133                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5134                         dist = r_refdef.view.clipplane.dist;
5135                 plane[0] = r_refdef.view.clipplane.normal[0];
5136                 plane[1] = r_refdef.view.clipplane.normal[1];
5137                 plane[2] = r_refdef.view.clipplane.normal[2];
5138                 plane[3] = dist;
5139                 customclipplane = plane;
5140         }
5141
5142         if (!r_refdef.view.useperspective)
5143                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -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);
5144         else if (vid.stencil && r_useinfinitefarclip.integer)
5145                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5146         else
5147                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5148         R_Mesh_SetMainRenderTargets();
5149         R_SetViewport(&r_refdef.view.viewport);
5150 }
5151
5152 void R_EntityMatrix(const matrix4x4_t *matrix)
5153 {
5154         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5155         {
5156                 gl_modelmatrixchanged = false;
5157                 gl_modelmatrix = *matrix;
5158                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5159                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5160                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5161                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5162                 CHECKGLERROR
5163                 switch(vid.renderpath)
5164                 {
5165                 case RENDERPATH_D3D9:
5166 #ifdef SUPPORTD3D
5167                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5168                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5169 #endif
5170                         break;
5171                 case RENDERPATH_D3D10:
5172                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5173                         break;
5174                 case RENDERPATH_D3D11:
5175                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5176                         break;
5177                 case RENDERPATH_GL13:
5178                 case RENDERPATH_GL11:
5179                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5180                         break;
5181                 case RENDERPATH_SOFT:
5182                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5183                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5184                         break;
5185                 case RENDERPATH_GL20:
5186                 case RENDERPATH_GLES2:
5187                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5188                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5189                         break;
5190                 }
5191         }
5192 }
5193
5194 void R_ResetViewRendering2D(void)
5195 {
5196         r_viewport_t viewport;
5197         DrawQ_Finish();
5198
5199         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5200         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);
5201         R_Mesh_ResetRenderTargets();
5202         R_SetViewport(&viewport);
5203         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5204         GL_Color(1, 1, 1, 1);
5205         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5206         GL_BlendFunc(GL_ONE, GL_ZERO);
5207         GL_ScissorTest(false);
5208         GL_DepthMask(false);
5209         GL_DepthRange(0, 1);
5210         GL_DepthTest(false);
5211         GL_DepthFunc(GL_LEQUAL);
5212         R_EntityMatrix(&identitymatrix);
5213         R_Mesh_ResetTextureState();
5214         GL_PolygonOffset(0, 0);
5215         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5216         switch(vid.renderpath)
5217         {
5218         case RENDERPATH_GL11:
5219         case RENDERPATH_GL13:
5220         case RENDERPATH_GL20:
5221         case RENDERPATH_GLES2:
5222                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5223                 break;
5224         case RENDERPATH_D3D9:
5225         case RENDERPATH_D3D10:
5226         case RENDERPATH_D3D11:
5227         case RENDERPATH_SOFT:
5228                 break;
5229         }
5230         GL_CullFace(GL_NONE);
5231 }
5232
5233 void R_ResetViewRendering3D(void)
5234 {
5235         DrawQ_Finish();
5236
5237         R_SetupView(true);
5238         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5239         GL_Color(1, 1, 1, 1);
5240         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5241         GL_BlendFunc(GL_ONE, GL_ZERO);
5242         GL_ScissorTest(true);
5243         GL_DepthMask(true);
5244         GL_DepthRange(0, 1);
5245         GL_DepthTest(true);
5246         GL_DepthFunc(GL_LEQUAL);
5247         R_EntityMatrix(&identitymatrix);
5248         R_Mesh_ResetTextureState();
5249         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5250         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5251         switch(vid.renderpath)
5252         {
5253         case RENDERPATH_GL11:
5254         case RENDERPATH_GL13:
5255         case RENDERPATH_GL20:
5256         case RENDERPATH_GLES2:
5257                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5258                 break;
5259         case RENDERPATH_D3D9:
5260         case RENDERPATH_D3D10:
5261         case RENDERPATH_D3D11:
5262         case RENDERPATH_SOFT:
5263                 break;
5264         }
5265         GL_CullFace(r_refdef.view.cullface_back);
5266 }
5267
5268 /*
5269 ================
5270 R_RenderView_UpdateViewVectors
5271 ================
5272 */
5273 static void R_RenderView_UpdateViewVectors(void)
5274 {
5275         // break apart the view matrix into vectors for various purposes
5276         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5277         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5278         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5279         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5280         // make an inverted copy of the view matrix for tracking sprites
5281         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5282 }
5283
5284 void R_RenderScene(void);
5285 void R_RenderWaterPlanes(void);
5286
5287 static void R_Water_StartFrame(void)
5288 {
5289         int i;
5290         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5291         r_waterstate_waterplane_t *p;
5292
5293         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5294                 return;
5295
5296         switch(vid.renderpath)
5297         {
5298         case RENDERPATH_GL20:
5299         case RENDERPATH_D3D9:
5300         case RENDERPATH_D3D10:
5301         case RENDERPATH_D3D11:
5302         case RENDERPATH_SOFT:
5303         case RENDERPATH_GLES2:
5304                 break;
5305         case RENDERPATH_GL13:
5306         case RENDERPATH_GL11:
5307                 return;
5308         }
5309
5310         // set waterwidth and waterheight to the water resolution that will be
5311         // used (often less than the screen resolution for faster rendering)
5312         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5313         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5314
5315         // calculate desired texture sizes
5316         // can't use water if the card does not support the texture size
5317         if (!r_water.integer || r_showsurfaces.integer)
5318                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5319         else if (vid.support.arb_texture_non_power_of_two)
5320         {
5321                 texturewidth = waterwidth;
5322                 textureheight = waterheight;
5323                 camerawidth = waterwidth;
5324                 cameraheight = waterheight;
5325         }
5326         else
5327         {
5328                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5329                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5330                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5331                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5332         }
5333
5334         // allocate textures as needed
5335         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5336         {
5337                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5338                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5339                 {
5340                         if (p->texture_refraction)
5341                                 R_FreeTexture(p->texture_refraction);
5342                         p->texture_refraction = NULL;
5343                         if (p->texture_reflection)
5344                                 R_FreeTexture(p->texture_reflection);
5345                         p->texture_reflection = NULL;
5346                         if (p->texture_camera)
5347                                 R_FreeTexture(p->texture_camera);
5348                         p->texture_camera = NULL;
5349                 }
5350                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5351                 r_waterstate.texturewidth = texturewidth;
5352                 r_waterstate.textureheight = textureheight;
5353                 r_waterstate.camerawidth = camerawidth;
5354                 r_waterstate.cameraheight = cameraheight;
5355         }
5356
5357         if (r_waterstate.texturewidth)
5358         {
5359                 r_waterstate.enabled = true;
5360
5361                 // when doing a reduced render (HDR) we want to use a smaller area
5362                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5363                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5364
5365                 // set up variables that will be used in shader setup
5366                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5367                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5368                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5369                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5370         }
5371
5372         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5373         r_waterstate.numwaterplanes = 0;
5374 }
5375
5376 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5377 {
5378         int triangleindex, planeindex;
5379         const int *e;
5380         vec3_t vert[3];
5381         vec3_t normal;
5382         vec3_t center;
5383         mplane_t plane;
5384         r_waterstate_waterplane_t *p;
5385         texture_t *t = R_GetCurrentTexture(surface->texture);
5386
5387         // just use the first triangle with a valid normal for any decisions
5388         VectorClear(normal);
5389         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5390         {
5391                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5392                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5393                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5394                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5395                 if (VectorLength2(normal) >= 0.001)
5396                         break;
5397         }
5398
5399         VectorCopy(normal, plane.normal);
5400         VectorNormalize(plane.normal);
5401         plane.dist = DotProduct(vert[0], plane.normal);
5402         PlaneClassify(&plane);
5403         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5404         {
5405                 // skip backfaces (except if nocullface is set)
5406                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5407                         return;
5408                 VectorNegate(plane.normal, plane.normal);
5409                 plane.dist *= -1;
5410                 PlaneClassify(&plane);
5411         }
5412
5413
5414         // find a matching plane if there is one
5415         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5416                 if(p->camera_entity == t->camera_entity)
5417                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5418                                 break;
5419         if (planeindex >= r_waterstate.maxwaterplanes)
5420                 return; // nothing we can do, out of planes
5421
5422         // if this triangle does not fit any known plane rendered this frame, add one
5423         if (planeindex >= r_waterstate.numwaterplanes)
5424         {
5425                 // store the new plane
5426                 r_waterstate.numwaterplanes++;
5427                 p->plane = plane;
5428                 // clear materialflags and pvs
5429                 p->materialflags = 0;
5430                 p->pvsvalid = false;
5431                 p->camera_entity = t->camera_entity;
5432                 VectorCopy(surface->mins, p->mins);
5433                 VectorCopy(surface->maxs, p->maxs);
5434         }
5435         else
5436         {
5437                 // merge mins/maxs
5438                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5439                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5440                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5441                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5442                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5443                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5444         }
5445         // merge this surface's materialflags into the waterplane
5446         p->materialflags |= t->currentmaterialflags;
5447         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5448         {
5449                 // merge this surface's PVS into the waterplane
5450                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5451                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5452                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5453                 {
5454                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5455                         p->pvsvalid = true;
5456                 }
5457         }
5458 }
5459
5460 static void R_Water_ProcessPlanes(void)
5461 {
5462         int myscissor[4];
5463         r_refdef_view_t originalview;
5464         r_refdef_view_t myview;
5465         int planeindex;
5466         r_waterstate_waterplane_t *p;
5467         vec3_t visorigin;
5468
5469         originalview = r_refdef.view;
5470
5471         // make sure enough textures are allocated
5472         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5473         {
5474                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5475                 {
5476                         if (!p->texture_refraction)
5477                                 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);
5478                         if (!p->texture_refraction)
5479                                 goto error;
5480                 }
5481                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5482                 {
5483                         if (!p->texture_camera)
5484                                 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);
5485                         if (!p->texture_camera)
5486                                 goto error;
5487                 }
5488
5489                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5490                 {
5491                         if (!p->texture_reflection)
5492                                 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);
5493                         if (!p->texture_reflection)
5494                                 goto error;
5495                 }
5496         }
5497
5498         // render views
5499         r_refdef.view = originalview;
5500         r_refdef.view.showdebug = false;
5501         r_refdef.view.width = r_waterstate.waterwidth;
5502         r_refdef.view.height = r_waterstate.waterheight;
5503         r_refdef.view.useclipplane = true;
5504         myview = r_refdef.view;
5505         r_waterstate.renderingscene = true;
5506         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5507         {
5508                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5509                 {
5510                         r_refdef.view = myview;
5511                         if(r_water_scissormode.integer)
5512                         {
5513                                 R_SetupView(true);
5514                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5515                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5516                         }
5517
5518                         // render reflected scene and copy into texture
5519                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5520                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5521                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5522                         r_refdef.view.clipplane = p->plane;
5523
5524                         // reverse the cullface settings for this render
5525                         r_refdef.view.cullface_front = GL_FRONT;
5526                         r_refdef.view.cullface_back = GL_BACK;
5527                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5528                         {
5529                                 r_refdef.view.usecustompvs = true;
5530                                 if (p->pvsvalid)
5531                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5532                                 else
5533                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5534                         }
5535
5536                         R_ResetViewRendering3D();
5537                         R_ClearScreen(r_refdef.fogenabled);
5538                         if(r_water_scissormode.integer & 2)
5539                                 R_View_UpdateWithScissor(myscissor);
5540                         else
5541                                 R_View_Update();
5542                         if(r_water_scissormode.integer & 1)
5543                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5544                         R_RenderScene();
5545
5546                         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);
5547                 }
5548
5549                 // render the normal view scene and copy into texture
5550                 // (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)
5551                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5552                 {
5553                         r_refdef.view = myview;
5554                         if(r_water_scissormode.integer)
5555                         {
5556                                 R_SetupView(true);
5557                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5558                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5559                         }
5560
5561                         r_waterstate.renderingrefraction = true;
5562
5563                         r_refdef.view.clipplane = p->plane;
5564                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5565                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5566
5567                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5568                         {
5569                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5570                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5571                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5572                                 R_RenderView_UpdateViewVectors();
5573                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5574                                 {
5575                                         r_refdef.view.usecustompvs = true;
5576                                         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);
5577                                 }
5578                         }
5579
5580                         PlaneClassify(&r_refdef.view.clipplane);
5581
5582                         R_ResetViewRendering3D();
5583                         R_ClearScreen(r_refdef.fogenabled);
5584                         if(r_water_scissormode.integer & 2)
5585                                 R_View_UpdateWithScissor(myscissor);
5586                         else
5587                                 R_View_Update();
5588                         if(r_water_scissormode.integer & 1)
5589                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5590                         R_RenderScene();
5591
5592                         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);
5593                         r_waterstate.renderingrefraction = false;
5594                 }
5595                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5596                 {
5597                         r_refdef.view = myview;
5598
5599                         r_refdef.view.clipplane = p->plane;
5600                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5601                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5602
5603                         r_refdef.view.width = r_waterstate.camerawidth;
5604                         r_refdef.view.height = r_waterstate.cameraheight;
5605                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5606                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5607
5608                         if(p->camera_entity)
5609                         {
5610                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5611                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5612                         }
5613
5614                         // note: all of the view is used for displaying... so
5615                         // there is no use in scissoring
5616
5617                         // reverse the cullface settings for this render
5618                         r_refdef.view.cullface_front = GL_FRONT;
5619                         r_refdef.view.cullface_back = GL_BACK;
5620                         // also reverse the view matrix
5621                         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
5622                         R_RenderView_UpdateViewVectors();
5623                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5624                         {
5625                                 r_refdef.view.usecustompvs = true;
5626                                 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);
5627                         }
5628                         
5629                         // camera needs no clipplane
5630                         r_refdef.view.useclipplane = false;
5631
5632                         PlaneClassify(&r_refdef.view.clipplane);
5633
5634                         R_ResetViewRendering3D();
5635                         R_ClearScreen(r_refdef.fogenabled);
5636                         R_View_Update();
5637                         R_RenderScene();
5638
5639                         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);
5640                         r_waterstate.renderingrefraction = false;
5641                 }
5642
5643         }
5644         r_waterstate.renderingscene = false;
5645         r_refdef.view = originalview;
5646         R_ResetViewRendering3D();
5647         R_ClearScreen(r_refdef.fogenabled);
5648         R_View_Update();
5649         return;
5650 error:
5651         r_refdef.view = originalview;
5652         r_waterstate.renderingscene = false;
5653         Cvar_SetValueQuick(&r_water, 0);
5654         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5655         return;
5656 }
5657
5658 void R_Bloom_StartFrame(void)
5659 {
5660         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5661         textype_t textype;
5662
5663         switch(vid.renderpath)
5664         {
5665         case RENDERPATH_GL20:
5666         case RENDERPATH_D3D9:
5667         case RENDERPATH_D3D10:
5668         case RENDERPATH_D3D11:
5669         case RENDERPATH_SOFT:
5670         case RENDERPATH_GLES2:
5671                 break;
5672         case RENDERPATH_GL13:
5673         case RENDERPATH_GL11:
5674                 return;
5675         }
5676
5677         // set bloomwidth and bloomheight to the bloom resolution that will be
5678         // used (often less than the screen resolution for faster rendering)
5679         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5680         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5681         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5682         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5683         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5684
5685         // calculate desired texture sizes
5686         if (vid.support.arb_texture_non_power_of_two)
5687         {
5688                 screentexturewidth = r_refdef.view.width;
5689                 screentextureheight = r_refdef.view.height;
5690                 bloomtexturewidth = r_bloomstate.bloomwidth;
5691                 bloomtextureheight = r_bloomstate.bloomheight;
5692         }
5693         else
5694         {
5695                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5696                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5697                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5698                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5699         }
5700
5701         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))
5702         {
5703                 Cvar_SetValueQuick(&r_hdr, 0);
5704                 Cvar_SetValueQuick(&r_bloom, 0);
5705                 Cvar_SetValueQuick(&r_motionblur, 0);
5706                 Cvar_SetValueQuick(&r_damageblur, 0);
5707         }
5708
5709         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)
5710                 screentexturewidth = screentextureheight = 0;
5711         if (!r_hdr.integer && !r_bloom.integer)
5712                 bloomtexturewidth = bloomtextureheight = 0;
5713
5714         textype = TEXTYPE_COLORBUFFER;
5715         switch (vid.renderpath)
5716         {
5717         case RENDERPATH_GL20:
5718         case RENDERPATH_GLES2:
5719                 if (vid.support.ext_framebuffer_object)
5720                 {
5721                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5722                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5723                 }
5724                 break;
5725         case RENDERPATH_D3D9:
5726         case RENDERPATH_D3D10:
5727         case RENDERPATH_D3D11:
5728         case RENDERPATH_SOFT:
5729         case RENDERPATH_GL13:
5730         case RENDERPATH_GL11:
5731                 break;
5732         }
5733
5734         // allocate textures as needed
5735         if (r_bloomstate.screentexturewidth != screentexturewidth
5736          || r_bloomstate.screentextureheight != screentextureheight
5737          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5738          || r_bloomstate.bloomtextureheight != bloomtextureheight
5739          || r_bloomstate.texturetype != textype
5740          || r_bloomstate.viewfbo != r_viewfbo.integer)
5741         {
5742                 if (r_bloomstate.texture_bloom)
5743                         R_FreeTexture(r_bloomstate.texture_bloom);
5744                 r_bloomstate.texture_bloom = NULL;
5745                 if (r_bloomstate.texture_screen)
5746                         R_FreeTexture(r_bloomstate.texture_screen);
5747                 r_bloomstate.texture_screen = NULL;
5748                 if (r_bloomstate.fbo_framebuffer)
5749                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5750                 r_bloomstate.fbo_framebuffer = 0;
5751                 if (r_bloomstate.texture_framebuffercolor)
5752                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5753                 r_bloomstate.texture_framebuffercolor = NULL;
5754                 if (r_bloomstate.texture_framebufferdepth)
5755                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5756                 r_bloomstate.texture_framebufferdepth = NULL;
5757                 r_bloomstate.screentexturewidth = screentexturewidth;
5758                 r_bloomstate.screentextureheight = screentextureheight;
5759                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5760                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
5761                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5762                 {
5763                         // FIXME: choose depth bits based on a cvar
5764                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5765                         r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
5766                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5767                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5768                         // render depth into one texture and normalmap into the other
5769                         if (qglDrawBuffer)
5770                         {
5771                                 int status;
5772                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5773                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5774                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5775                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5776                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5777                         }
5778                 }
5779                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5780                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5781                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5782                         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);
5783                 r_bloomstate.viewfbo = r_viewfbo.integer;
5784                 r_bloomstate.texturetype = textype;
5785         }
5786
5787         // when doing a reduced render (HDR) we want to use a smaller area
5788         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5789         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5790         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5791         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5792         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5793
5794         // set up a texcoord array for the full resolution screen image
5795         // (we have to keep this around to copy back during final render)
5796         r_bloomstate.screentexcoord2f[0] = 0;
5797         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5798         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5799         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5800         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5801         r_bloomstate.screentexcoord2f[5] = 0;
5802         r_bloomstate.screentexcoord2f[6] = 0;
5803         r_bloomstate.screentexcoord2f[7] = 0;
5804
5805         // set up a texcoord array for the reduced resolution bloom image
5806         // (which will be additive blended over the screen image)
5807         r_bloomstate.bloomtexcoord2f[0] = 0;
5808         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5809         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5810         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5811         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5812         r_bloomstate.bloomtexcoord2f[5] = 0;
5813         r_bloomstate.bloomtexcoord2f[6] = 0;
5814         r_bloomstate.bloomtexcoord2f[7] = 0;
5815
5816         switch(vid.renderpath)
5817         {
5818         case RENDERPATH_GL11:
5819         case RENDERPATH_GL13:
5820         case RENDERPATH_GL20:
5821         case RENDERPATH_SOFT:
5822         case RENDERPATH_GLES2:
5823                 break;
5824         case RENDERPATH_D3D9:
5825         case RENDERPATH_D3D10:
5826         case RENDERPATH_D3D11:
5827                 {
5828                         int i;
5829                         for (i = 0;i < 4;i++)
5830                         {
5831                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5832                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5833                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5834                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5835                         }
5836                 }
5837                 break;
5838         }
5839
5840         if (r_hdr.integer || r_bloom.integer)
5841         {
5842                 r_bloomstate.enabled = true;
5843                 r_bloomstate.hdr = r_hdr.integer != 0;
5844         }
5845
5846         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);
5847
5848         if (r_bloomstate.fbo_framebuffer)
5849                 r_refdef.view.clear = true;
5850 }
5851
5852 void R_Bloom_CopyBloomTexture(float colorscale)
5853 {
5854         r_refdef.stats.bloom++;
5855
5856         // scale down screen texture to the bloom texture size
5857         CHECKGLERROR
5858         R_Mesh_SetMainRenderTargets();
5859         R_SetViewport(&r_bloomstate.viewport);
5860         GL_BlendFunc(GL_ONE, GL_ZERO);
5861         GL_Color(colorscale, colorscale, colorscale, 1);
5862         // 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...
5863         switch(vid.renderpath)
5864         {
5865         case RENDERPATH_GL11:
5866         case RENDERPATH_GL13:
5867         case RENDERPATH_GL20:
5868         case RENDERPATH_SOFT:
5869         case RENDERPATH_GLES2:
5870                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5871                 break;
5872         case RENDERPATH_D3D9:
5873         case RENDERPATH_D3D10:
5874         case RENDERPATH_D3D11:
5875                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5876                 break;
5877         }
5878         // TODO: do boxfilter scale-down in shader?
5879         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5880         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5881         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5882
5883         // we now have a bloom image in the framebuffer
5884         // copy it into the bloom image texture for later processing
5885         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);
5886         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5887 }
5888
5889 void R_Bloom_CopyHDRTexture(void)
5890 {
5891         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);
5892         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5893 }
5894
5895 void R_Bloom_MakeTexture(void)
5896 {
5897         int x, range, dir;
5898         float xoffset, yoffset, r, brighten;
5899
5900         r_refdef.stats.bloom++;
5901
5902         R_ResetViewRendering2D();
5903
5904         // we have a bloom image in the framebuffer
5905         CHECKGLERROR
5906         R_SetViewport(&r_bloomstate.viewport);
5907
5908         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5909         {
5910                 x *= 2;
5911                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5912                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5913                 GL_Color(r,r,r,1);
5914                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5915                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5916                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5917                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5918
5919                 // copy the vertically blurred bloom view to a texture
5920                 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);
5921                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5922         }
5923
5924         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5925         brighten = r_bloom_brighten.value;
5926         if (r_hdr.integer)
5927                 brighten *= r_hdr_range.value;
5928         brighten = sqrt(brighten);
5929         if(range >= 1)
5930                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5931         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5932
5933         for (dir = 0;dir < 2;dir++)
5934         {
5935                 // blend on at multiple vertical offsets to achieve a vertical blur
5936                 // TODO: do offset blends using GLSL
5937                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5938                 GL_BlendFunc(GL_ONE, GL_ZERO);
5939                 for (x = -range;x <= range;x++)
5940                 {
5941                         if (!dir){xoffset = 0;yoffset = x;}
5942                         else {xoffset = x;yoffset = 0;}
5943                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5944                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5945                         // compute a texcoord array with the specified x and y offset
5946                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5947                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5948                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5949                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5950                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5951                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5952                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5953                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5954                         // this r value looks like a 'dot' particle, fading sharply to
5955                         // black at the edges
5956                         // (probably not realistic but looks good enough)
5957                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5958                         //r = brighten/(range*2+1);
5959                         r = brighten / (range * 2 + 1);
5960                         if(range >= 1)
5961                                 r *= (1 - x*x/(float)(range*range));
5962                         GL_Color(r, r, r, 1);
5963                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5964                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5965                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5966                         GL_BlendFunc(GL_ONE, GL_ONE);
5967                 }
5968
5969                 // copy the vertically blurred bloom view to a texture
5970                 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);
5971                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5972         }
5973 }
5974
5975 void R_HDR_RenderBloomTexture(void)
5976 {
5977         int oldwidth, oldheight;
5978         float oldcolorscale;
5979         qboolean oldwaterstate;
5980
5981         oldwaterstate = r_waterstate.enabled;
5982         oldcolorscale = r_refdef.view.colorscale;
5983         oldwidth = r_refdef.view.width;
5984         oldheight = r_refdef.view.height;
5985         r_refdef.view.width = r_bloomstate.bloomwidth;
5986         r_refdef.view.height = r_bloomstate.bloomheight;
5987
5988         if(r_hdr.integer < 2)
5989                 r_waterstate.enabled = false;
5990
5991         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5992         // TODO: add exposure compensation features
5993         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5994
5995         r_refdef.view.showdebug = false;
5996         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5997
5998         R_ResetViewRendering3D();
5999
6000         R_ClearScreen(r_refdef.fogenabled);
6001         if (r_timereport_active)
6002                 R_TimeReport("HDRclear");
6003
6004         R_View_Update();
6005         if (r_timereport_active)
6006                 R_TimeReport("visibility");
6007
6008         // only do secondary renders with HDR if r_hdr is 2 or higher
6009         r_waterstate.numwaterplanes = 0;
6010         if (r_waterstate.enabled)
6011                 R_RenderWaterPlanes();
6012
6013         r_refdef.view.showdebug = true;
6014         R_RenderScene();
6015         r_waterstate.numwaterplanes = 0;
6016
6017         R_ResetViewRendering2D();
6018
6019         R_Bloom_CopyHDRTexture();
6020         R_Bloom_MakeTexture();
6021
6022         // restore the view settings
6023         r_waterstate.enabled = oldwaterstate;
6024         r_refdef.view.width = oldwidth;
6025         r_refdef.view.height = oldheight;
6026         r_refdef.view.colorscale = oldcolorscale;
6027
6028         R_ResetViewRendering3D();
6029
6030         R_ClearScreen(r_refdef.fogenabled);
6031         if (r_timereport_active)
6032                 R_TimeReport("viewclear");
6033 }
6034
6035 static void R_BlendView(void)
6036 {
6037         unsigned int permutation;
6038         float uservecs[4][4];
6039
6040         switch (vid.renderpath)
6041         {
6042         case RENDERPATH_GL20:
6043         case RENDERPATH_D3D9:
6044         case RENDERPATH_D3D10:
6045         case RENDERPATH_D3D11:
6046         case RENDERPATH_SOFT:
6047         case RENDERPATH_GLES2:
6048                 permutation =
6049                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6050                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6051                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6052                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6053                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6054
6055                 if (r_bloomstate.texture_screen)
6056                 {
6057                         // make sure the buffer is available
6058                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6059
6060                         R_ResetViewRendering2D();
6061                         R_Mesh_SetMainRenderTargets();
6062
6063                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6064                         {
6065                                 // declare variables
6066                                 float speed;
6067                                 static float avgspeed;
6068
6069                                 speed = VectorLength(cl.movement_velocity);
6070
6071                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6072                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6073
6074                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6075                                 speed = bound(0, speed, 1);
6076                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6077
6078                                 // calculate values into a standard alpha
6079                                 cl.motionbluralpha = 1 - exp(-
6080                                                 (
6081                                                  (r_motionblur.value * speed / 80)
6082                                                  +
6083                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6084                                                 )
6085                                                 /
6086                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6087                                            );
6088
6089                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6090                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6091                                 // apply the blur
6092                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6093                                 {
6094                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6095                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6096                                         switch(vid.renderpath)
6097                                         {
6098                                         case RENDERPATH_GL11:
6099                                         case RENDERPATH_GL13:
6100                                         case RENDERPATH_GL20:
6101                                         case RENDERPATH_SOFT:
6102                                         case RENDERPATH_GLES2:
6103                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6104                                                 break;
6105                                         case RENDERPATH_D3D9:
6106                                         case RENDERPATH_D3D10:
6107                                         case RENDERPATH_D3D11:
6108                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6109                                                 break;
6110                                         }
6111                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6112                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6113                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6114                                 }
6115                         }
6116
6117                         // copy view into the screen texture
6118                         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);
6119                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6120                 }
6121                 else if (!r_bloomstate.texture_bloom)
6122                 {
6123                         // we may still have to do view tint...
6124                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6125                         {
6126                                 // apply a color tint to the whole view
6127                                 R_ResetViewRendering2D();
6128                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6129                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6130                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6131                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6132                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6133                         }
6134                         break; // no screen processing, no bloom, skip it
6135                 }
6136
6137                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6138                 {
6139                         // render simple bloom effect
6140                         // copy the screen and shrink it and darken it for the bloom process
6141                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6142                         // make the bloom texture
6143                         R_Bloom_MakeTexture();
6144                 }
6145
6146 #if _MSC_VER >= 1400
6147 #define sscanf sscanf_s
6148 #endif
6149                 memset(uservecs, 0, sizeof(uservecs));
6150                 if (r_glsl_postprocess_uservec1_enable.integer)
6151                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6152                 if (r_glsl_postprocess_uservec2_enable.integer)
6153                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6154                 if (r_glsl_postprocess_uservec3_enable.integer)
6155                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6156                 if (r_glsl_postprocess_uservec4_enable.integer)
6157                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6158
6159                 R_ResetViewRendering2D();
6160                 GL_Color(1, 1, 1, 1);
6161                 GL_BlendFunc(GL_ONE, GL_ZERO);
6162
6163                 switch(vid.renderpath)
6164                 {
6165                 case RENDERPATH_GL20:
6166                 case RENDERPATH_GLES2:
6167                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6168                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6169                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6170                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6171                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6172                         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]);
6173                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6174                         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]);
6175                         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]);
6176                         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]);
6177                         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]);
6178                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6179                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6180                         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);
6181                         break;
6182                 case RENDERPATH_D3D9:
6183 #ifdef SUPPORTD3D
6184                         // 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...
6185                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6186                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6187                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6188                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6189                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6190                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6191                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6192                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6193                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6194                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6195                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6196                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6197                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6198                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6199 #endif
6200                         break;
6201                 case RENDERPATH_D3D10:
6202                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6203                         break;
6204                 case RENDERPATH_D3D11:
6205                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6206                         break;
6207                 case RENDERPATH_SOFT:
6208                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6209                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6210                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6211                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6212                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6213                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6214                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6215                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6216                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6217                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6218                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6219                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6220                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6221                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6222                         break;
6223                 default:
6224                         break;
6225                 }
6226                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6227                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6228                 break;
6229         case RENDERPATH_GL13:
6230         case RENDERPATH_GL11:
6231                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6232                 {
6233                         // apply a color tint to the whole view
6234                         R_ResetViewRendering2D();
6235                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6236                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6237                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6238                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6239                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6240                 }
6241                 break;
6242         }
6243 }
6244
6245 matrix4x4_t r_waterscrollmatrix;
6246
6247 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6248 {
6249         if (r_refdef.fog_density)
6250         {
6251                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6252                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6253                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6254
6255                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6256                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6257                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6258                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6259
6260                 {
6261                         vec3_t fogvec;
6262                         VectorCopy(r_refdef.fogcolor, fogvec);
6263                         //   color.rgb *= ContrastBoost * SceneBrightness;
6264                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6265                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6266                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6267                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6268                 }
6269         }
6270 }
6271
6272 void R_UpdateVariables(void)
6273 {
6274         R_Textures_Frame();
6275
6276         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6277
6278         r_refdef.farclip = r_farclip_base.value;
6279         if (r_refdef.scene.worldmodel)
6280                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6281         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6282
6283         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6284                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6285         r_refdef.polygonfactor = 0;
6286         r_refdef.polygonoffset = 0;
6287         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6288         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6289
6290         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6291         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6292         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6293         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6294         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6295         if (FAKELIGHT_ENABLED)
6296         {
6297                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6298         }
6299         if (r_showsurfaces.integer)
6300         {
6301                 r_refdef.scene.rtworld = false;
6302                 r_refdef.scene.rtworldshadows = false;
6303                 r_refdef.scene.rtdlight = false;
6304                 r_refdef.scene.rtdlightshadows = false;
6305                 r_refdef.lightmapintensity = 0;
6306         }
6307
6308         if (gamemode == GAME_NEHAHRA)
6309         {
6310                 if (gl_fogenable.integer)
6311                 {
6312                         r_refdef.oldgl_fogenable = true;
6313                         r_refdef.fog_density = gl_fogdensity.value;
6314                         r_refdef.fog_red = gl_fogred.value;
6315                         r_refdef.fog_green = gl_foggreen.value;
6316                         r_refdef.fog_blue = gl_fogblue.value;
6317                         r_refdef.fog_alpha = 1;
6318                         r_refdef.fog_start = 0;
6319                         r_refdef.fog_end = gl_skyclip.value;
6320                         r_refdef.fog_height = 1<<30;
6321                         r_refdef.fog_fadedepth = 128;
6322                 }
6323                 else if (r_refdef.oldgl_fogenable)
6324                 {
6325                         r_refdef.oldgl_fogenable = false;
6326                         r_refdef.fog_density = 0;
6327                         r_refdef.fog_red = 0;
6328                         r_refdef.fog_green = 0;
6329                         r_refdef.fog_blue = 0;
6330                         r_refdef.fog_alpha = 0;
6331                         r_refdef.fog_start = 0;
6332                         r_refdef.fog_end = 0;
6333                         r_refdef.fog_height = 1<<30;
6334                         r_refdef.fog_fadedepth = 128;
6335                 }
6336         }
6337
6338         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6339         r_refdef.fog_start = max(0, r_refdef.fog_start);
6340         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6341
6342         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6343
6344         if (r_refdef.fog_density && r_drawfog.integer)
6345         {
6346                 r_refdef.fogenabled = true;
6347                 // this is the point where the fog reaches 0.9986 alpha, which we
6348                 // consider a good enough cutoff point for the texture
6349                 // (0.9986 * 256 == 255.6)
6350                 if (r_fog_exp2.integer)
6351                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6352                 else
6353                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6354                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6355                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6356                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6357                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6358                         R_BuildFogHeightTexture();
6359                 // fog color was already set
6360                 // update the fog texture
6361                 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)
6362                         R_BuildFogTexture();
6363                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6364                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6365         }
6366         else
6367                 r_refdef.fogenabled = false;
6368
6369         switch(vid.renderpath)
6370         {
6371         case RENDERPATH_GL20:
6372         case RENDERPATH_D3D9:
6373         case RENDERPATH_D3D10:
6374         case RENDERPATH_D3D11:
6375         case RENDERPATH_SOFT:
6376         case RENDERPATH_GLES2:
6377                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6378                 {
6379                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6380                         {
6381                                 // build GLSL gamma texture
6382 #define RAMPWIDTH 256
6383                                 unsigned short ramp[RAMPWIDTH * 3];
6384                                 unsigned char rampbgr[RAMPWIDTH][4];
6385                                 int i;
6386
6387                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6388
6389                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6390                                 for(i = 0; i < RAMPWIDTH; ++i)
6391                                 {
6392                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6393                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6394                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6395                                         rampbgr[i][3] = 0;
6396                                 }
6397                                 if (r_texture_gammaramps)
6398                                 {
6399                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6400                                 }
6401                                 else
6402                                 {
6403                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6404                                 }
6405                         }
6406                 }
6407                 else
6408                 {
6409                         // remove GLSL gamma texture
6410                 }
6411                 break;
6412         case RENDERPATH_GL13:
6413         case RENDERPATH_GL11:
6414                 break;
6415         }
6416 }
6417
6418 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6419 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6420 /*
6421 ================
6422 R_SelectScene
6423 ================
6424 */
6425 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6426         if( scenetype != r_currentscenetype ) {
6427                 // store the old scenetype
6428                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6429                 r_currentscenetype = scenetype;
6430                 // move in the new scene
6431                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6432         }
6433 }
6434
6435 /*
6436 ================
6437 R_GetScenePointer
6438 ================
6439 */
6440 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6441 {
6442         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6443         if( scenetype == r_currentscenetype ) {
6444                 return &r_refdef.scene;
6445         } else {
6446                 return &r_scenes_store[ scenetype ];
6447         }
6448 }
6449
6450 /*
6451 ================
6452 R_RenderView
6453 ================
6454 */
6455 int dpsoftrast_test;
6456 void R_RenderView(void)
6457 {
6458         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6459
6460         dpsoftrast_test = r_test.integer;
6461
6462         if (r_timereport_active)
6463                 R_TimeReport("start");
6464         r_textureframe++; // used only by R_GetCurrentTexture
6465         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6466
6467         if(R_CompileShader_CheckStaticParms())
6468                 R_GLSL_Restart_f();
6469
6470         if (!r_drawentities.integer)
6471                 r_refdef.scene.numentities = 0;
6472
6473         R_AnimCache_ClearCache();
6474         R_FrameData_NewFrame();
6475
6476         /* adjust for stereo display */
6477         if(R_Stereo_Active())
6478         {
6479                 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);
6480                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6481         }
6482
6483         if (r_refdef.view.isoverlay)
6484         {
6485                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6486                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6487                 R_TimeReport("depthclear");
6488
6489                 r_refdef.view.showdebug = false;
6490
6491                 r_waterstate.enabled = false;
6492                 r_waterstate.numwaterplanes = 0;
6493
6494                 R_RenderScene();
6495
6496                 r_refdef.view.matrix = originalmatrix;
6497
6498                 CHECKGLERROR
6499                 return;
6500         }
6501
6502         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6503         {
6504                 r_refdef.view.matrix = originalmatrix;
6505                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6506         }
6507
6508         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6509
6510         R_RenderView_UpdateViewVectors();
6511
6512         R_Shadow_UpdateWorldLightSelection();
6513
6514         R_Bloom_StartFrame();
6515         R_Water_StartFrame();
6516
6517         CHECKGLERROR
6518         if (r_timereport_active)
6519                 R_TimeReport("viewsetup");
6520
6521         R_ResetViewRendering3D();
6522
6523         if (r_refdef.view.clear || r_refdef.fogenabled)
6524         {
6525                 R_ClearScreen(r_refdef.fogenabled);
6526                 if (r_timereport_active)
6527                         R_TimeReport("viewclear");
6528         }
6529         r_refdef.view.clear = true;
6530
6531         // this produces a bloom texture to be used in R_BlendView() later
6532         if (r_hdr.integer && r_bloomstate.bloomwidth)
6533         {
6534                 R_HDR_RenderBloomTexture();
6535                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6536                 r_textureframe++; // used only by R_GetCurrentTexture
6537         }
6538
6539         r_refdef.view.showdebug = true;
6540
6541         R_View_Update();
6542         if (r_timereport_active)
6543                 R_TimeReport("visibility");
6544
6545         r_waterstate.numwaterplanes = 0;
6546         if (r_waterstate.enabled)
6547                 R_RenderWaterPlanes();
6548
6549         R_RenderScene();
6550         r_waterstate.numwaterplanes = 0;
6551
6552         R_BlendView();
6553         if (r_timereport_active)
6554                 R_TimeReport("blendview");
6555
6556         GL_Scissor(0, 0, vid.width, vid.height);
6557         GL_ScissorTest(false);
6558
6559         r_refdef.view.matrix = originalmatrix;
6560
6561         CHECKGLERROR
6562 }
6563
6564 void R_RenderWaterPlanes(void)
6565 {
6566         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6567         {
6568                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6569                 if (r_timereport_active)
6570                         R_TimeReport("waterworld");
6571         }
6572
6573         // don't let sound skip if going slow
6574         if (r_refdef.scene.extraupdate)
6575                 S_ExtraUpdate ();
6576
6577         R_DrawModelsAddWaterPlanes();
6578         if (r_timereport_active)
6579                 R_TimeReport("watermodels");
6580
6581         if (r_waterstate.numwaterplanes)
6582         {
6583                 R_Water_ProcessPlanes();
6584                 if (r_timereport_active)
6585                         R_TimeReport("waterscenes");
6586         }
6587 }
6588
6589 extern void R_DrawLightningBeams (void);
6590 extern void VM_CL_AddPolygonsToMeshQueue (void);
6591 extern void R_DrawPortals (void);
6592 extern cvar_t cl_locs_show;
6593 static void R_DrawLocs(void);
6594 static void R_DrawEntityBBoxes(void);
6595 static void R_DrawModelDecals(void);
6596 extern void R_DrawModelShadows(void);
6597 extern void R_DrawModelShadowMaps(void);
6598 extern cvar_t cl_decals_newsystem;
6599 extern qboolean r_shadow_usingdeferredprepass;
6600 void R_RenderScene(void)
6601 {
6602         qboolean shadowmapping = false;
6603
6604         if (r_timereport_active)
6605                 R_TimeReport("beginscene");
6606
6607         r_refdef.stats.renders++;
6608
6609         R_UpdateFogColor();
6610
6611         // don't let sound skip if going slow
6612         if (r_refdef.scene.extraupdate)
6613                 S_ExtraUpdate ();
6614
6615         R_MeshQueue_BeginScene();
6616
6617         R_SkyStartFrame();
6618
6619         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);
6620
6621         if (r_timereport_active)
6622                 R_TimeReport("skystartframe");
6623
6624         if (cl.csqc_vidvars.drawworld)
6625         {
6626                 // don't let sound skip if going slow
6627                 if (r_refdef.scene.extraupdate)
6628                         S_ExtraUpdate ();
6629
6630                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6631                 {
6632                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6633                         if (r_timereport_active)
6634                                 R_TimeReport("worldsky");
6635                 }
6636
6637                 if (R_DrawBrushModelsSky() && r_timereport_active)
6638                         R_TimeReport("bmodelsky");
6639
6640                 if (skyrendermasked && skyrenderlater)
6641                 {
6642                         // we have to force off the water clipping plane while rendering sky
6643                         R_SetupView(false);
6644                         R_Sky();
6645                         R_SetupView(true);
6646                         if (r_timereport_active)
6647                                 R_TimeReport("sky");
6648                 }
6649         }
6650
6651         R_AnimCache_CacheVisibleEntities();
6652         if (r_timereport_active)
6653                 R_TimeReport("animation");
6654
6655         R_Shadow_PrepareLights();
6656         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6657                 R_Shadow_PrepareModelShadows();
6658         if (r_timereport_active)
6659                 R_TimeReport("preparelights");
6660
6661         if (R_Shadow_ShadowMappingEnabled())
6662                 shadowmapping = true;
6663
6664         if (r_shadow_usingdeferredprepass)
6665                 R_Shadow_DrawPrepass();
6666
6667         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6668         {
6669                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6670                 if (r_timereport_active)
6671                         R_TimeReport("worlddepth");
6672         }
6673         if (r_depthfirst.integer >= 2)
6674         {
6675                 R_DrawModelsDepth();
6676                 if (r_timereport_active)
6677                         R_TimeReport("modeldepth");
6678         }
6679
6680         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6681         {
6682                 R_DrawModelShadowMaps();
6683                 R_ResetViewRendering3D();
6684                 // don't let sound skip if going slow
6685                 if (r_refdef.scene.extraupdate)
6686                         S_ExtraUpdate ();
6687         }
6688
6689         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6690         {
6691                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6692                 if (r_timereport_active)
6693                         R_TimeReport("world");
6694         }
6695
6696         // don't let sound skip if going slow
6697         if (r_refdef.scene.extraupdate)
6698                 S_ExtraUpdate ();
6699
6700         R_DrawModels();
6701         if (r_timereport_active)
6702                 R_TimeReport("models");
6703
6704         // don't let sound skip if going slow
6705         if (r_refdef.scene.extraupdate)
6706                 S_ExtraUpdate ();
6707
6708         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6709         {
6710                 R_DrawModelShadows();
6711                 R_ResetViewRendering3D();
6712                 // don't let sound skip if going slow
6713                 if (r_refdef.scene.extraupdate)
6714                         S_ExtraUpdate ();
6715         }
6716
6717         if (!r_shadow_usingdeferredprepass)
6718         {
6719                 R_Shadow_DrawLights();
6720                 if (r_timereport_active)
6721                         R_TimeReport("rtlights");
6722         }
6723
6724         // don't let sound skip if going slow
6725         if (r_refdef.scene.extraupdate)
6726                 S_ExtraUpdate ();
6727
6728         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6729         {
6730                 R_DrawModelShadows();
6731                 R_ResetViewRendering3D();
6732                 // don't let sound skip if going slow
6733                 if (r_refdef.scene.extraupdate)
6734                         S_ExtraUpdate ();
6735         }
6736
6737         if (cl.csqc_vidvars.drawworld)
6738         {
6739                 if (cl_decals_newsystem.integer)
6740                 {
6741                         R_DrawModelDecals();
6742                         if (r_timereport_active)
6743                                 R_TimeReport("modeldecals");
6744                 }
6745                 else
6746                 {
6747                         R_DrawDecals();
6748                         if (r_timereport_active)
6749                                 R_TimeReport("decals");
6750                 }
6751
6752                 R_DrawParticles();
6753                 if (r_timereport_active)
6754                         R_TimeReport("particles");
6755
6756                 R_DrawExplosions();
6757                 if (r_timereport_active)
6758                         R_TimeReport("explosions");
6759
6760                 R_DrawLightningBeams();
6761                 if (r_timereport_active)
6762                         R_TimeReport("lightning");
6763         }
6764
6765         VM_CL_AddPolygonsToMeshQueue();
6766
6767         if (r_refdef.view.showdebug)
6768         {
6769                 if (cl_locs_show.integer)
6770                 {
6771                         R_DrawLocs();
6772                         if (r_timereport_active)
6773                                 R_TimeReport("showlocs");
6774                 }
6775
6776                 if (r_drawportals.integer)
6777                 {
6778                         R_DrawPortals();
6779                         if (r_timereport_active)
6780                                 R_TimeReport("portals");
6781                 }
6782
6783                 if (r_showbboxes.value > 0)
6784                 {
6785                         R_DrawEntityBBoxes();
6786                         if (r_timereport_active)
6787                                 R_TimeReport("bboxes");
6788                 }
6789         }
6790
6791         R_MeshQueue_RenderTransparent();
6792         if (r_timereport_active)
6793                 R_TimeReport("drawtrans");
6794
6795         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))
6796         {
6797                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6798                 if (r_timereport_active)
6799                         R_TimeReport("worlddebug");
6800                 R_DrawModelsDebug();
6801                 if (r_timereport_active)
6802                         R_TimeReport("modeldebug");
6803         }
6804
6805         if (cl.csqc_vidvars.drawworld)
6806         {
6807                 R_Shadow_DrawCoronas();
6808                 if (r_timereport_active)
6809                         R_TimeReport("coronas");
6810         }
6811
6812 #if 0
6813         {
6814                 GL_DepthTest(false);
6815                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6816                 GL_Color(1, 1, 1, 1);
6817                 qglBegin(GL_POLYGON);
6818                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6819                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6820                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6821                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6822                 qglEnd();
6823                 qglBegin(GL_POLYGON);
6824                 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]);
6825                 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]);
6826                 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]);
6827                 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]);
6828                 qglEnd();
6829                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6830         }
6831 #endif
6832
6833         // don't let sound skip if going slow
6834         if (r_refdef.scene.extraupdate)
6835                 S_ExtraUpdate ();
6836
6837         R_ResetViewRendering2D();
6838 }
6839
6840 static const unsigned short bboxelements[36] =
6841 {
6842         5, 1, 3, 5, 3, 7,
6843         6, 2, 0, 6, 0, 4,
6844         7, 3, 2, 7, 2, 6,
6845         4, 0, 1, 4, 1, 5,
6846         4, 5, 7, 4, 7, 6,
6847         1, 0, 2, 1, 2, 3,
6848 };
6849
6850 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6851 {
6852         int i;
6853         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6854
6855         RSurf_ActiveWorldEntity();
6856
6857         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6858         GL_DepthMask(false);
6859         GL_DepthRange(0, 1);
6860         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6861 //      R_Mesh_ResetTextureState();
6862
6863         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6864         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6865         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6866         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6867         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6868         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6869         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6870         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6871         R_FillColors(color4f, 8, cr, cg, cb, ca);
6872         if (r_refdef.fogenabled)
6873         {
6874                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6875                 {
6876                         f1 = RSurf_FogVertex(v);
6877                         f2 = 1 - f1;
6878                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6879                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6880                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6881                 }
6882         }
6883         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6884         R_Mesh_ResetTextureState();
6885         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6886         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6887 }
6888
6889 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6890 {
6891         int i;
6892         float color[4];
6893         prvm_edict_t *edict;
6894         prvm_prog_t *prog_save = prog;
6895
6896         // this function draws bounding boxes of server entities
6897         if (!sv.active)
6898                 return;
6899
6900         GL_CullFace(GL_NONE);
6901         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6902
6903         prog = 0;
6904         SV_VM_Begin();
6905         for (i = 0;i < numsurfaces;i++)
6906         {
6907                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6908                 switch ((int)edict->fields.server->solid)
6909                 {
6910                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6911                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6912                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6913                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6914                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6915                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6916                 }
6917                 color[3] *= r_showbboxes.value;
6918                 color[3] = bound(0, color[3], 1);
6919                 GL_DepthTest(!r_showdisabledepthtest.integer);
6920                 GL_CullFace(r_refdef.view.cullface_front);
6921                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6922         }
6923         SV_VM_End();
6924         prog = prog_save;
6925 }
6926
6927 static void R_DrawEntityBBoxes(void)
6928 {
6929         int i;
6930         prvm_edict_t *edict;
6931         vec3_t center;
6932         prvm_prog_t *prog_save = prog;
6933
6934         // this function draws bounding boxes of server entities
6935         if (!sv.active)
6936                 return;
6937
6938         prog = 0;
6939         SV_VM_Begin();
6940         for (i = 0;i < prog->num_edicts;i++)
6941         {
6942                 edict = PRVM_EDICT_NUM(i);
6943                 if (edict->priv.server->free)
6944                         continue;
6945                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6946                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6947                         continue;
6948                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6949                         continue;
6950                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6951                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6952         }
6953         SV_VM_End();
6954         prog = prog_save;
6955 }
6956
6957 static const int nomodelelement3i[24] =
6958 {
6959         5, 2, 0,
6960         5, 1, 2,
6961         5, 0, 3,
6962         5, 3, 1,
6963         0, 2, 4,
6964         2, 1, 4,
6965         3, 0, 4,
6966         1, 3, 4
6967 };
6968
6969 static const unsigned short nomodelelement3s[24] =
6970 {
6971         5, 2, 0,
6972         5, 1, 2,
6973         5, 0, 3,
6974         5, 3, 1,
6975         0, 2, 4,
6976         2, 1, 4,
6977         3, 0, 4,
6978         1, 3, 4
6979 };
6980
6981 static const float nomodelvertex3f[6*3] =
6982 {
6983         -16,   0,   0,
6984          16,   0,   0,
6985           0, -16,   0,
6986           0,  16,   0,
6987           0,   0, -16,
6988           0,   0,  16
6989 };
6990
6991 static const float nomodelcolor4f[6*4] =
6992 {
6993         0.0f, 0.0f, 0.5f, 1.0f,
6994         0.0f, 0.0f, 0.5f, 1.0f,
6995         0.0f, 0.5f, 0.0f, 1.0f,
6996         0.0f, 0.5f, 0.0f, 1.0f,
6997         0.5f, 0.0f, 0.0f, 1.0f,
6998         0.5f, 0.0f, 0.0f, 1.0f
6999 };
7000
7001 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7002 {
7003         int i;
7004         float f1, f2, *c;
7005         float color4f[6*4];
7006
7007         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);
7008
7009         // this is only called once per entity so numsurfaces is always 1, and
7010         // surfacelist is always {0}, so this code does not handle batches
7011
7012         if (rsurface.ent_flags & RENDER_ADDITIVE)
7013         {
7014                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7015                 GL_DepthMask(false);
7016         }
7017         else if (rsurface.colormod[3] < 1)
7018         {
7019                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7020                 GL_DepthMask(false);
7021         }
7022         else
7023         {
7024                 GL_BlendFunc(GL_ONE, GL_ZERO);
7025                 GL_DepthMask(true);
7026         }
7027         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7028         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7029         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7030         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7031         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7032         for (i = 0, c = color4f;i < 6;i++, c += 4)
7033         {
7034                 c[0] *= rsurface.colormod[0];
7035                 c[1] *= rsurface.colormod[1];
7036                 c[2] *= rsurface.colormod[2];
7037                 c[3] *= rsurface.colormod[3];
7038         }
7039         if (r_refdef.fogenabled)
7040         {
7041                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7042                 {
7043                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7044                         f2 = 1 - f1;
7045                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7046                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7047                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7048                 }
7049         }
7050 //      R_Mesh_ResetTextureState();
7051         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7052         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7053         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7054 }
7055
7056 void R_DrawNoModel(entity_render_t *ent)
7057 {
7058         vec3_t org;
7059         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7060         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7061                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7062         else
7063                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7064 }
7065
7066 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7067 {
7068         vec3_t right1, right2, diff, normal;
7069
7070         VectorSubtract (org2, org1, normal);
7071
7072         // calculate 'right' vector for start
7073         VectorSubtract (r_refdef.view.origin, org1, diff);
7074         CrossProduct (normal, diff, right1);
7075         VectorNormalize (right1);
7076
7077         // calculate 'right' vector for end
7078         VectorSubtract (r_refdef.view.origin, org2, diff);
7079         CrossProduct (normal, diff, right2);
7080         VectorNormalize (right2);
7081
7082         vert[ 0] = org1[0] + width * right1[0];
7083         vert[ 1] = org1[1] + width * right1[1];
7084         vert[ 2] = org1[2] + width * right1[2];
7085         vert[ 3] = org1[0] - width * right1[0];
7086         vert[ 4] = org1[1] - width * right1[1];
7087         vert[ 5] = org1[2] - width * right1[2];
7088         vert[ 6] = org2[0] - width * right2[0];
7089         vert[ 7] = org2[1] - width * right2[1];
7090         vert[ 8] = org2[2] - width * right2[2];
7091         vert[ 9] = org2[0] + width * right2[0];
7092         vert[10] = org2[1] + width * right2[1];
7093         vert[11] = org2[2] + width * right2[2];
7094 }
7095
7096 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)
7097 {
7098         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7099         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7100         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7101         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7102         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7103         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7104         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7105         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7106         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7107         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7108         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7109         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7110 }
7111
7112 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7113 {
7114         int i;
7115         float *vertex3f;
7116         float v[3];
7117         VectorSet(v, x, y, z);
7118         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7119                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7120                         break;
7121         if (i == mesh->numvertices)
7122         {
7123                 if (mesh->numvertices < mesh->maxvertices)
7124                 {
7125                         VectorCopy(v, vertex3f);
7126                         mesh->numvertices++;
7127                 }
7128                 return mesh->numvertices;
7129         }
7130         else
7131                 return i;
7132 }
7133
7134 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7135 {
7136         int i;
7137         int *e, element[3];
7138         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7139         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7140         e = mesh->element3i + mesh->numtriangles * 3;
7141         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7142         {
7143                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7144                 if (mesh->numtriangles < mesh->maxtriangles)
7145                 {
7146                         *e++ = element[0];
7147                         *e++ = element[1];
7148                         *e++ = element[2];
7149                         mesh->numtriangles++;
7150                 }
7151                 element[1] = element[2];
7152         }
7153 }
7154
7155 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7156 {
7157         int i;
7158         int *e, element[3];
7159         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7160         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7161         e = mesh->element3i + mesh->numtriangles * 3;
7162         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7163         {
7164                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7165                 if (mesh->numtriangles < mesh->maxtriangles)
7166                 {
7167                         *e++ = element[0];
7168                         *e++ = element[1];
7169                         *e++ = element[2];
7170                         mesh->numtriangles++;
7171                 }
7172                 element[1] = element[2];
7173         }
7174 }
7175
7176 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7177 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7178 {
7179         int planenum, planenum2;
7180         int w;
7181         int tempnumpoints;
7182         mplane_t *plane, *plane2;
7183         double maxdist;
7184         double temppoints[2][256*3];
7185         // figure out how large a bounding box we need to properly compute this brush
7186         maxdist = 0;
7187         for (w = 0;w < numplanes;w++)
7188                 maxdist = max(maxdist, fabs(planes[w].dist));
7189         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7190         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7191         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7192         {
7193                 w = 0;
7194                 tempnumpoints = 4;
7195                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7196                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7197                 {
7198                         if (planenum2 == planenum)
7199                                 continue;
7200                         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);
7201                         w = !w;
7202                 }
7203                 if (tempnumpoints < 3)
7204                         continue;
7205                 // generate elements forming a triangle fan for this polygon
7206                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7207         }
7208 }
7209
7210 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)
7211 {
7212         texturelayer_t *layer;
7213         layer = t->currentlayers + t->currentnumlayers++;
7214         layer->type = type;
7215         layer->depthmask = depthmask;
7216         layer->blendfunc1 = blendfunc1;
7217         layer->blendfunc2 = blendfunc2;
7218         layer->texture = texture;
7219         layer->texmatrix = *matrix;
7220         layer->color[0] = r;
7221         layer->color[1] = g;
7222         layer->color[2] = b;
7223         layer->color[3] = a;
7224 }
7225
7226 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7227 {
7228         if(parms[0] == 0 && parms[1] == 0)
7229                 return false;
7230         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7231                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7232                         return false;
7233         return true;
7234 }
7235
7236 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7237 {
7238         double index, f;
7239         index = parms[2] + r_refdef.scene.time * parms[3];
7240         index -= floor(index);
7241         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7242         {
7243         default:
7244         case Q3WAVEFUNC_NONE:
7245         case Q3WAVEFUNC_NOISE:
7246         case Q3WAVEFUNC_COUNT:
7247                 f = 0;
7248                 break;
7249         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7250         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7251         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7252         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7253         case Q3WAVEFUNC_TRIANGLE:
7254                 index *= 4;
7255                 f = index - floor(index);
7256                 if (index < 1)
7257                         f = f;
7258                 else if (index < 2)
7259                         f = 1 - f;
7260                 else if (index < 3)
7261                         f = -f;
7262                 else
7263                         f = -(1 - f);
7264                 break;
7265         }
7266         f = parms[0] + parms[1] * f;
7267         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7268                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7269         return (float) f;
7270 }
7271
7272 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7273 {
7274         int w, h, idx;
7275         float f;
7276         float tcmat[12];
7277         matrix4x4_t matrix, temp;
7278         switch(tcmod->tcmod)
7279         {
7280                 case Q3TCMOD_COUNT:
7281                 case Q3TCMOD_NONE:
7282                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7283                                 matrix = r_waterscrollmatrix;
7284                         else
7285                                 matrix = identitymatrix;
7286                         break;
7287                 case Q3TCMOD_ENTITYTRANSLATE:
7288                         // this is used in Q3 to allow the gamecode to control texcoord
7289                         // scrolling on the entity, which is not supported in darkplaces yet.
7290                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7291                         break;
7292                 case Q3TCMOD_ROTATE:
7293                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7294                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7295                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7296                         break;
7297                 case Q3TCMOD_SCALE:
7298                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7299                         break;
7300                 case Q3TCMOD_SCROLL:
7301                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7302                         break;
7303                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7304                         w = (int) tcmod->parms[0];
7305                         h = (int) tcmod->parms[1];
7306                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7307                         f = f - floor(f);
7308                         idx = (int) floor(f * w * h);
7309                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7310                         break;
7311                 case Q3TCMOD_STRETCH:
7312                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7313                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7314                         break;
7315                 case Q3TCMOD_TRANSFORM:
7316                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7317                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7318                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7319                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7320                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7321                         break;
7322                 case Q3TCMOD_TURBULENT:
7323                         // this is handled in the RSurf_PrepareVertices function
7324                         matrix = identitymatrix;
7325                         break;
7326         }
7327         temp = *texmatrix;
7328         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7329 }
7330
7331 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7332 {
7333         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7334         char name[MAX_QPATH];
7335         skinframe_t *skinframe;
7336         unsigned char pixels[296*194];
7337         strlcpy(cache->name, skinname, sizeof(cache->name));
7338         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7339         if (developer_loading.integer)
7340                 Con_Printf("loading %s\n", name);
7341         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7342         if (!skinframe || !skinframe->base)
7343         {
7344                 unsigned char *f;
7345                 fs_offset_t filesize;
7346                 skinframe = NULL;
7347                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7348                 if (f)
7349                 {
7350                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7351                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7352                         Mem_Free(f);
7353                 }
7354         }
7355         cache->skinframe = skinframe;
7356 }
7357
7358 texture_t *R_GetCurrentTexture(texture_t *t)
7359 {
7360         int i;
7361         const entity_render_t *ent = rsurface.entity;
7362         dp_model_t *model = ent->model;
7363         q3shaderinfo_layer_tcmod_t *tcmod;
7364
7365         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7366                 return t->currentframe;
7367         t->update_lastrenderframe = r_textureframe;
7368         t->update_lastrenderentity = (void *)ent;
7369
7370         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7371                 t->camera_entity = ent->entitynumber;
7372         else
7373                 t->camera_entity = 0;
7374
7375         // switch to an alternate material if this is a q1bsp animated material
7376         {
7377                 texture_t *texture = t;
7378                 int s = rsurface.ent_skinnum;
7379                 if ((unsigned int)s >= (unsigned int)model->numskins)
7380                         s = 0;
7381                 if (model->skinscenes)
7382                 {
7383                         if (model->skinscenes[s].framecount > 1)
7384                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7385                         else
7386                                 s = model->skinscenes[s].firstframe;
7387                 }
7388                 if (s > 0)
7389                         t = t + s * model->num_surfaces;
7390                 if (t->animated)
7391                 {
7392                         // use an alternate animation if the entity's frame is not 0,
7393                         // and only if the texture has an alternate animation
7394                         if (rsurface.ent_alttextures && t->anim_total[1])
7395                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7396                         else
7397                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7398                 }
7399                 texture->currentframe = t;
7400         }
7401
7402         // update currentskinframe to be a qw skin or animation frame
7403         if (rsurface.ent_qwskin >= 0)
7404         {
7405                 i = rsurface.ent_qwskin;
7406                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7407                 {
7408                         r_qwskincache_size = cl.maxclients;
7409                         if (r_qwskincache)
7410                                 Mem_Free(r_qwskincache);
7411                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7412                 }
7413                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7414                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7415                 t->currentskinframe = r_qwskincache[i].skinframe;
7416                 if (t->currentskinframe == NULL)
7417                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7418         }
7419         else if (t->numskinframes >= 2)
7420                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7421         if (t->backgroundnumskinframes >= 2)
7422                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7423
7424         t->currentmaterialflags = t->basematerialflags;
7425         t->currentalpha = rsurface.colormod[3];
7426         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7427                 t->currentalpha *= r_wateralpha.value;
7428         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7429                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7430         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7431                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7432         if (!(rsurface.ent_flags & RENDER_LIGHT))
7433                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7434         else if (FAKELIGHT_ENABLED)
7435         {
7436                         // no modellight if using fakelight for the map
7437         }
7438         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7439         {
7440                 // pick a model lighting mode
7441                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7442                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7443                 else
7444                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7445         }
7446         if (rsurface.ent_flags & RENDER_ADDITIVE)
7447                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7448         else if (t->currentalpha < 1)
7449                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7450         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7451                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7452         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7453                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7454         if (t->backgroundnumskinframes)
7455                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7456         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7457         {
7458                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7459                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7460         }
7461         else
7462                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7463         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7464                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7465
7466         // there is no tcmod
7467         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7468         {
7469                 t->currenttexmatrix = r_waterscrollmatrix;
7470                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7471         }
7472         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7473         {
7474                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7475                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7476         }
7477
7478         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7479                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7480         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7481                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7482
7483         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7484         if (t->currentskinframe->qpixels)
7485                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7486         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7487         if (!t->basetexture)
7488                 t->basetexture = r_texture_notexture;
7489         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7490         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7491         t->nmaptexture = t->currentskinframe->nmap;
7492         if (!t->nmaptexture)
7493                 t->nmaptexture = r_texture_blanknormalmap;
7494         t->glosstexture = r_texture_black;
7495         t->glowtexture = t->currentskinframe->glow;
7496         t->fogtexture = t->currentskinframe->fog;
7497         t->reflectmasktexture = t->currentskinframe->reflect;
7498         if (t->backgroundnumskinframes)
7499         {
7500                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7501                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7502                 t->backgroundglosstexture = r_texture_black;
7503                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7504                 if (!t->backgroundnmaptexture)
7505                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7506         }
7507         else
7508         {
7509                 t->backgroundbasetexture = r_texture_white;
7510                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7511                 t->backgroundglosstexture = r_texture_black;
7512                 t->backgroundglowtexture = NULL;
7513         }
7514         t->specularpower = r_shadow_glossexponent.value;
7515         // TODO: store reference values for these in the texture?
7516         t->specularscale = 0;
7517         if (r_shadow_gloss.integer > 0)
7518         {
7519                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7520                 {
7521                         if (r_shadow_glossintensity.value > 0)
7522                         {
7523                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7524                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7525                                 t->specularscale = r_shadow_glossintensity.value;
7526                         }
7527                 }
7528                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7529                 {
7530                         t->glosstexture = r_texture_white;
7531                         t->backgroundglosstexture = r_texture_white;
7532                         t->specularscale = r_shadow_gloss2intensity.value;
7533                         t->specularpower = r_shadow_gloss2exponent.value;
7534                 }
7535         }
7536         t->specularscale *= t->specularscalemod;
7537         t->specularpower *= t->specularpowermod;
7538
7539         // lightmaps mode looks bad with dlights using actual texturing, so turn
7540         // off the colormap and glossmap, but leave the normalmap on as it still
7541         // accurately represents the shading involved
7542         if (gl_lightmaps.integer)
7543         {
7544                 t->basetexture = r_texture_grey128;
7545                 t->pantstexture = r_texture_black;
7546                 t->shirttexture = r_texture_black;
7547                 t->nmaptexture = r_texture_blanknormalmap;
7548                 t->glosstexture = r_texture_black;
7549                 t->glowtexture = NULL;
7550                 t->fogtexture = NULL;
7551                 t->reflectmasktexture = NULL;
7552                 t->backgroundbasetexture = NULL;
7553                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7554                 t->backgroundglosstexture = r_texture_black;
7555                 t->backgroundglowtexture = NULL;
7556                 t->specularscale = 0;
7557                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7558         }
7559
7560         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7561         VectorClear(t->dlightcolor);
7562         t->currentnumlayers = 0;
7563         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7564         {
7565                 int blendfunc1, blendfunc2;
7566                 qboolean depthmask;
7567                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7568                 {
7569                         blendfunc1 = GL_SRC_ALPHA;
7570                         blendfunc2 = GL_ONE;
7571                 }
7572                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7573                 {
7574                         blendfunc1 = GL_SRC_ALPHA;
7575                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7576                 }
7577                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7578                 {
7579                         blendfunc1 = t->customblendfunc[0];
7580                         blendfunc2 = t->customblendfunc[1];
7581                 }
7582                 else
7583                 {
7584                         blendfunc1 = GL_ONE;
7585                         blendfunc2 = GL_ZERO;
7586                 }
7587                 // don't colormod evilblend textures
7588                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7589                         VectorSet(t->lightmapcolor, 1, 1, 1);
7590                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7591                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7592                 {
7593                         // fullbright is not affected by r_refdef.lightmapintensity
7594                         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]);
7595                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7596                                 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]);
7597                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7598                                 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]);
7599                 }
7600                 else
7601                 {
7602                         vec3_t ambientcolor;
7603                         float colorscale;
7604                         // set the color tint used for lights affecting this surface
7605                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7606                         colorscale = 2;
7607                         // q3bsp has no lightmap updates, so the lightstylevalue that
7608                         // would normally be baked into the lightmap must be
7609                         // applied to the color
7610                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7611                         if (model->type == mod_brushq3)
7612                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7613                         colorscale *= r_refdef.lightmapintensity;
7614                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7615                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7616                         // basic lit geometry
7617                         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]);
7618                         // add pants/shirt if needed
7619                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7620                                 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]);
7621                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7622                                 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]);
7623                         // now add ambient passes if needed
7624                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7625                         {
7626                                 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]);
7627                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7628                                         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]);
7629                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7630                                         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]);
7631                         }
7632                 }
7633                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7634                         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]);
7635                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7636                 {
7637                         // if this is opaque use alpha blend which will darken the earlier
7638                         // passes cheaply.
7639                         //
7640                         // if this is an alpha blended material, all the earlier passes
7641                         // were darkened by fog already, so we only need to add the fog
7642                         // color ontop through the fog mask texture
7643                         //
7644                         // if this is an additive blended material, all the earlier passes
7645                         // were darkened by fog already, and we should not add fog color
7646                         // (because the background was not darkened, there is no fog color
7647                         // that was lost behind it).
7648                         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]);
7649                 }
7650         }
7651
7652         return t->currentframe;
7653 }
7654
7655 rsurfacestate_t rsurface;
7656
7657 void RSurf_ActiveWorldEntity(void)
7658 {
7659         dp_model_t *model = r_refdef.scene.worldmodel;
7660         //if (rsurface.entity == r_refdef.scene.worldentity)
7661         //      return;
7662         rsurface.entity = r_refdef.scene.worldentity;
7663         rsurface.skeleton = NULL;
7664         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7665         rsurface.ent_skinnum = 0;
7666         rsurface.ent_qwskin = -1;
7667         rsurface.ent_shadertime = 0;
7668         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7669         rsurface.matrix = identitymatrix;
7670         rsurface.inversematrix = identitymatrix;
7671         rsurface.matrixscale = 1;
7672         rsurface.inversematrixscale = 1;
7673         R_EntityMatrix(&identitymatrix);
7674         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7675         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7676         rsurface.fograngerecip = r_refdef.fograngerecip;
7677         rsurface.fogheightfade = r_refdef.fogheightfade;
7678         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7679         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7680         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7681         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7682         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7683         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7684         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7685         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7686         rsurface.colormod[3] = 1;
7687         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);
7688         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7689         rsurface.frameblend[0].lerp = 1;
7690         rsurface.ent_alttextures = false;
7691         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7692         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7693         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7694         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7695         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7696         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7697         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7698         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7699         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7700         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7701         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7702         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7703         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7704         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7705         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7706         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7707         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7708         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7709         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7710         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7711         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7712         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7713         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7714         rsurface.modelelement3i = model->surfmesh.data_element3i;
7715         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7716         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7717         rsurface.modelelement3s = model->surfmesh.data_element3s;
7718         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7719         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7720         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7721         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7722         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7723         rsurface.modelsurfaces = model->data_surfaces;
7724         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7725         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7726         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7727         rsurface.modelgeneratedvertex = false;
7728         rsurface.batchgeneratedvertex = false;
7729         rsurface.batchfirstvertex = 0;
7730         rsurface.batchnumvertices = 0;
7731         rsurface.batchfirsttriangle = 0;
7732         rsurface.batchnumtriangles = 0;
7733         rsurface.batchvertex3f  = NULL;
7734         rsurface.batchvertex3f_vertexbuffer = NULL;
7735         rsurface.batchvertex3f_bufferoffset = 0;
7736         rsurface.batchsvector3f = NULL;
7737         rsurface.batchsvector3f_vertexbuffer = NULL;
7738         rsurface.batchsvector3f_bufferoffset = 0;
7739         rsurface.batchtvector3f = NULL;
7740         rsurface.batchtvector3f_vertexbuffer = NULL;
7741         rsurface.batchtvector3f_bufferoffset = 0;
7742         rsurface.batchnormal3f  = NULL;
7743         rsurface.batchnormal3f_vertexbuffer = NULL;
7744         rsurface.batchnormal3f_bufferoffset = 0;
7745         rsurface.batchlightmapcolor4f = NULL;
7746         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7747         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7748         rsurface.batchtexcoordtexture2f = NULL;
7749         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7750         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7751         rsurface.batchtexcoordlightmap2f = NULL;
7752         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7753         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7754         rsurface.batchvertexmesh = NULL;
7755         rsurface.batchvertexmeshbuffer = NULL;
7756         rsurface.batchvertex3fbuffer = NULL;
7757         rsurface.batchelement3i = NULL;
7758         rsurface.batchelement3i_indexbuffer = NULL;
7759         rsurface.batchelement3i_bufferoffset = 0;
7760         rsurface.batchelement3s = NULL;
7761         rsurface.batchelement3s_indexbuffer = NULL;
7762         rsurface.batchelement3s_bufferoffset = 0;
7763         rsurface.passcolor4f = NULL;
7764         rsurface.passcolor4f_vertexbuffer = NULL;
7765         rsurface.passcolor4f_bufferoffset = 0;
7766 }
7767
7768 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7769 {
7770         dp_model_t *model = ent->model;
7771         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7772         //      return;
7773         rsurface.entity = (entity_render_t *)ent;
7774         rsurface.skeleton = ent->skeleton;
7775         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7776         rsurface.ent_skinnum = ent->skinnum;
7777         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;
7778         rsurface.ent_shadertime = ent->shadertime;
7779         rsurface.ent_flags = ent->flags;
7780         rsurface.matrix = ent->matrix;
7781         rsurface.inversematrix = ent->inversematrix;
7782         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7783         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7784         R_EntityMatrix(&rsurface.matrix);
7785         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7786         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7787         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7788         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7789         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7790         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7791         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7792         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7793         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7794         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7795         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7796         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7797         rsurface.colormod[3] = ent->alpha;
7798         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7799         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7800         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7801         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7802         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7803         if (ent->model->brush.submodel && !prepass)
7804         {
7805                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7806                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7807         }
7808         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7809         {
7810                 if (ent->animcache_vertex3f)
7811                 {
7812                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7813                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7814                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7815                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7816                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7817                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7818                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7819                 }
7820                 else if (wanttangents)
7821                 {
7822                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7823                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7824                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7825                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7826                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7827                         rsurface.modelvertexmesh = NULL;
7828                         rsurface.modelvertexmeshbuffer = NULL;
7829                         rsurface.modelvertex3fbuffer = NULL;
7830                 }
7831                 else if (wantnormals)
7832                 {
7833                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7834                         rsurface.modelsvector3f = NULL;
7835                         rsurface.modeltvector3f = NULL;
7836                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7837                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7838                         rsurface.modelvertexmesh = NULL;
7839                         rsurface.modelvertexmeshbuffer = NULL;
7840                         rsurface.modelvertex3fbuffer = NULL;
7841                 }
7842                 else
7843                 {
7844                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7845                         rsurface.modelsvector3f = NULL;
7846                         rsurface.modeltvector3f = NULL;
7847                         rsurface.modelnormal3f = NULL;
7848                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7849                         rsurface.modelvertexmesh = NULL;
7850                         rsurface.modelvertexmeshbuffer = NULL;
7851                         rsurface.modelvertex3fbuffer = NULL;
7852                 }
7853                 rsurface.modelvertex3f_vertexbuffer = 0;
7854                 rsurface.modelvertex3f_bufferoffset = 0;
7855                 rsurface.modelsvector3f_vertexbuffer = 0;
7856                 rsurface.modelsvector3f_bufferoffset = 0;
7857                 rsurface.modeltvector3f_vertexbuffer = 0;
7858                 rsurface.modeltvector3f_bufferoffset = 0;
7859                 rsurface.modelnormal3f_vertexbuffer = 0;
7860                 rsurface.modelnormal3f_bufferoffset = 0;
7861                 rsurface.modelgeneratedvertex = true;
7862         }
7863         else
7864         {
7865                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7866                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7867                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7868                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7869                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7870                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7871                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7872                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7873                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7874                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7875                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7876                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7877                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7878                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7879                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7880                 rsurface.modelgeneratedvertex = false;
7881         }
7882         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7883         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7884         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7885         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7886         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7887         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7888         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7889         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7890         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7891         rsurface.modelelement3i = model->surfmesh.data_element3i;
7892         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7893         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7894         rsurface.modelelement3s = model->surfmesh.data_element3s;
7895         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7896         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7897         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7898         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7899         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7900         rsurface.modelsurfaces = model->data_surfaces;
7901         rsurface.batchgeneratedvertex = false;
7902         rsurface.batchfirstvertex = 0;
7903         rsurface.batchnumvertices = 0;
7904         rsurface.batchfirsttriangle = 0;
7905         rsurface.batchnumtriangles = 0;
7906         rsurface.batchvertex3f  = NULL;
7907         rsurface.batchvertex3f_vertexbuffer = NULL;
7908         rsurface.batchvertex3f_bufferoffset = 0;
7909         rsurface.batchsvector3f = NULL;
7910         rsurface.batchsvector3f_vertexbuffer = NULL;
7911         rsurface.batchsvector3f_bufferoffset = 0;
7912         rsurface.batchtvector3f = NULL;
7913         rsurface.batchtvector3f_vertexbuffer = NULL;
7914         rsurface.batchtvector3f_bufferoffset = 0;
7915         rsurface.batchnormal3f  = NULL;
7916         rsurface.batchnormal3f_vertexbuffer = NULL;
7917         rsurface.batchnormal3f_bufferoffset = 0;
7918         rsurface.batchlightmapcolor4f = NULL;
7919         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7920         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7921         rsurface.batchtexcoordtexture2f = NULL;
7922         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7923         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7924         rsurface.batchtexcoordlightmap2f = NULL;
7925         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7926         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7927         rsurface.batchvertexmesh = NULL;
7928         rsurface.batchvertexmeshbuffer = NULL;
7929         rsurface.batchvertex3fbuffer = NULL;
7930         rsurface.batchelement3i = NULL;
7931         rsurface.batchelement3i_indexbuffer = NULL;
7932         rsurface.batchelement3i_bufferoffset = 0;
7933         rsurface.batchelement3s = NULL;
7934         rsurface.batchelement3s_indexbuffer = NULL;
7935         rsurface.batchelement3s_bufferoffset = 0;
7936         rsurface.passcolor4f = NULL;
7937         rsurface.passcolor4f_vertexbuffer = NULL;
7938         rsurface.passcolor4f_bufferoffset = 0;
7939 }
7940
7941 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)
7942 {
7943         rsurface.entity = r_refdef.scene.worldentity;
7944         rsurface.skeleton = NULL;
7945         rsurface.ent_skinnum = 0;
7946         rsurface.ent_qwskin = -1;
7947         rsurface.ent_shadertime = shadertime;
7948         rsurface.ent_flags = entflags;
7949         rsurface.modelnumvertices = numvertices;
7950         rsurface.modelnumtriangles = numtriangles;
7951         rsurface.matrix = *matrix;
7952         rsurface.inversematrix = *inversematrix;
7953         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7954         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7955         R_EntityMatrix(&rsurface.matrix);
7956         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7957         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7958         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7959         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7960         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7961         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7962         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7963         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7964         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7965         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7966         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7967         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7968         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);
7969         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7970         rsurface.frameblend[0].lerp = 1;
7971         rsurface.ent_alttextures = false;
7972         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7973         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7974         if (wanttangents)
7975         {
7976                 rsurface.modelvertex3f = (float *)vertex3f;
7977                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7978                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7979                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7980         }
7981         else if (wantnormals)
7982         {
7983                 rsurface.modelvertex3f = (float *)vertex3f;
7984                 rsurface.modelsvector3f = NULL;
7985                 rsurface.modeltvector3f = NULL;
7986                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7987         }
7988         else
7989         {
7990                 rsurface.modelvertex3f = (float *)vertex3f;
7991                 rsurface.modelsvector3f = NULL;
7992                 rsurface.modeltvector3f = NULL;
7993                 rsurface.modelnormal3f = NULL;
7994         }
7995         rsurface.modelvertexmesh = NULL;
7996         rsurface.modelvertexmeshbuffer = NULL;
7997         rsurface.modelvertex3fbuffer = NULL;
7998         rsurface.modelvertex3f_vertexbuffer = 0;
7999         rsurface.modelvertex3f_bufferoffset = 0;
8000         rsurface.modelsvector3f_vertexbuffer = 0;
8001         rsurface.modelsvector3f_bufferoffset = 0;
8002         rsurface.modeltvector3f_vertexbuffer = 0;
8003         rsurface.modeltvector3f_bufferoffset = 0;
8004         rsurface.modelnormal3f_vertexbuffer = 0;
8005         rsurface.modelnormal3f_bufferoffset = 0;
8006         rsurface.modelgeneratedvertex = true;
8007         rsurface.modellightmapcolor4f  = (float *)color4f;
8008         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8009         rsurface.modellightmapcolor4f_bufferoffset = 0;
8010         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8011         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8012         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8013         rsurface.modeltexcoordlightmap2f  = NULL;
8014         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8015         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8016         rsurface.modelelement3i = (int *)element3i;
8017         rsurface.modelelement3i_indexbuffer = NULL;
8018         rsurface.modelelement3i_bufferoffset = 0;
8019         rsurface.modelelement3s = (unsigned short *)element3s;
8020         rsurface.modelelement3s_indexbuffer = NULL;
8021         rsurface.modelelement3s_bufferoffset = 0;
8022         rsurface.modellightmapoffsets = NULL;
8023         rsurface.modelsurfaces = NULL;
8024         rsurface.batchgeneratedvertex = false;
8025         rsurface.batchfirstvertex = 0;
8026         rsurface.batchnumvertices = 0;
8027         rsurface.batchfirsttriangle = 0;
8028         rsurface.batchnumtriangles = 0;
8029         rsurface.batchvertex3f  = NULL;
8030         rsurface.batchvertex3f_vertexbuffer = NULL;
8031         rsurface.batchvertex3f_bufferoffset = 0;
8032         rsurface.batchsvector3f = NULL;
8033         rsurface.batchsvector3f_vertexbuffer = NULL;
8034         rsurface.batchsvector3f_bufferoffset = 0;
8035         rsurface.batchtvector3f = NULL;
8036         rsurface.batchtvector3f_vertexbuffer = NULL;
8037         rsurface.batchtvector3f_bufferoffset = 0;
8038         rsurface.batchnormal3f  = NULL;
8039         rsurface.batchnormal3f_vertexbuffer = NULL;
8040         rsurface.batchnormal3f_bufferoffset = 0;
8041         rsurface.batchlightmapcolor4f = NULL;
8042         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8043         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8044         rsurface.batchtexcoordtexture2f = NULL;
8045         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8046         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8047         rsurface.batchtexcoordlightmap2f = NULL;
8048         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8049         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8050         rsurface.batchvertexmesh = NULL;
8051         rsurface.batchvertexmeshbuffer = NULL;
8052         rsurface.batchvertex3fbuffer = NULL;
8053         rsurface.batchelement3i = NULL;
8054         rsurface.batchelement3i_indexbuffer = NULL;
8055         rsurface.batchelement3i_bufferoffset = 0;
8056         rsurface.batchelement3s = NULL;
8057         rsurface.batchelement3s_indexbuffer = NULL;
8058         rsurface.batchelement3s_bufferoffset = 0;
8059         rsurface.passcolor4f = NULL;
8060         rsurface.passcolor4f_vertexbuffer = NULL;
8061         rsurface.passcolor4f_bufferoffset = 0;
8062
8063         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8064         {
8065                 if ((wantnormals || wanttangents) && !normal3f)
8066                 {
8067                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8068                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8069                 }
8070                 if (wanttangents && !svector3f)
8071                 {
8072                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8073                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8074                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8075                 }
8076         }
8077 }
8078
8079 float RSurf_FogPoint(const float *v)
8080 {
8081         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8082         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8083         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8084         float FogHeightFade = r_refdef.fogheightfade;
8085         float fogfrac;
8086         unsigned int fogmasktableindex;
8087         if (r_refdef.fogplaneviewabove)
8088                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8089         else
8090                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8091         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8092         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8093 }
8094
8095 float RSurf_FogVertex(const float *v)
8096 {
8097         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8098         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8099         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8100         float FogHeightFade = rsurface.fogheightfade;
8101         float fogfrac;
8102         unsigned int fogmasktableindex;
8103         if (r_refdef.fogplaneviewabove)
8104                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8105         else
8106                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8107         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8108         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8109 }
8110
8111 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8112 {
8113         int i;
8114         for (i = 0;i < numelements;i++)
8115                 outelement3i[i] = inelement3i[i] + adjust;
8116 }
8117
8118 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8119 extern cvar_t gl_vbo;
8120 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8121 {
8122         int deformindex;
8123         int firsttriangle;
8124         int numtriangles;
8125         int firstvertex;
8126         int endvertex;
8127         int numvertices;
8128         int surfacefirsttriangle;
8129         int surfacenumtriangles;
8130         int surfacefirstvertex;
8131         int surfaceendvertex;
8132         int surfacenumvertices;
8133         int batchnumvertices;
8134         int batchnumtriangles;
8135         int needsupdate;
8136         int i, j;
8137         qboolean gaps;
8138         qboolean dynamicvertex;
8139         float amplitude;
8140         float animpos;
8141         float scale;
8142         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8143         float waveparms[4];
8144         q3shaderinfo_deform_t *deform;
8145         const msurface_t *surface, *firstsurface;
8146         r_vertexmesh_t *vertexmesh;
8147         if (!texturenumsurfaces)
8148                 return;
8149         // find vertex range of this surface batch
8150         gaps = false;
8151         firstsurface = texturesurfacelist[0];
8152         firsttriangle = firstsurface->num_firsttriangle;
8153         batchnumvertices = 0;
8154         batchnumtriangles = 0;
8155         firstvertex = endvertex = firstsurface->num_firstvertex;
8156         for (i = 0;i < texturenumsurfaces;i++)
8157         {
8158                 surface = texturesurfacelist[i];
8159                 if (surface != firstsurface + i)
8160                         gaps = true;
8161                 surfacefirstvertex = surface->num_firstvertex;
8162                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8163                 surfacenumvertices = surface->num_vertices;
8164                 surfacenumtriangles = surface->num_triangles;
8165                 if (firstvertex > surfacefirstvertex)
8166                         firstvertex = surfacefirstvertex;
8167                 if (endvertex < surfaceendvertex)
8168                         endvertex = surfaceendvertex;
8169                 batchnumvertices += surfacenumvertices;
8170                 batchnumtriangles += surfacenumtriangles;
8171         }
8172
8173         // we now know the vertex range used, and if there are any gaps in it
8174         rsurface.batchfirstvertex = firstvertex;
8175         rsurface.batchnumvertices = endvertex - firstvertex;
8176         rsurface.batchfirsttriangle = firsttriangle;
8177         rsurface.batchnumtriangles = batchnumtriangles;
8178
8179         // this variable holds flags for which properties have been updated that
8180         // may require regenerating vertexmesh array...
8181         needsupdate = 0;
8182
8183         // check if any dynamic vertex processing must occur
8184         dynamicvertex = false;
8185
8186         // if there is a chance of animated vertex colors, it's a dynamic batch
8187         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8188         {
8189                 dynamicvertex = true;
8190                 batchneed |= BATCHNEED_NOGAPS;
8191                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8192         }
8193
8194         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8195         {
8196                 switch (deform->deform)
8197                 {
8198                 default:
8199                 case Q3DEFORM_PROJECTIONSHADOW:
8200                 case Q3DEFORM_TEXT0:
8201                 case Q3DEFORM_TEXT1:
8202                 case Q3DEFORM_TEXT2:
8203                 case Q3DEFORM_TEXT3:
8204                 case Q3DEFORM_TEXT4:
8205                 case Q3DEFORM_TEXT5:
8206                 case Q3DEFORM_TEXT6:
8207                 case Q3DEFORM_TEXT7:
8208                 case Q3DEFORM_NONE:
8209                         break;
8210                 case Q3DEFORM_AUTOSPRITE:
8211                         dynamicvertex = true;
8212                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8213                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8214                         break;
8215                 case Q3DEFORM_AUTOSPRITE2:
8216                         dynamicvertex = true;
8217                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8218                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8219                         break;
8220                 case Q3DEFORM_NORMAL:
8221                         dynamicvertex = true;
8222                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8223                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8224                         break;
8225                 case Q3DEFORM_WAVE:
8226                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8227                                 break; // if wavefunc is a nop, ignore this transform
8228                         dynamicvertex = true;
8229                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8230                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8231                         break;
8232                 case Q3DEFORM_BULGE:
8233                         dynamicvertex = true;
8234                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8235                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8236                         break;
8237                 case Q3DEFORM_MOVE:
8238                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8239                                 break; // if wavefunc is a nop, ignore this transform
8240                         dynamicvertex = true;
8241                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8242                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8243                         break;
8244                 }
8245         }
8246         switch(rsurface.texture->tcgen.tcgen)
8247         {
8248         default:
8249         case Q3TCGEN_TEXTURE:
8250                 break;
8251         case Q3TCGEN_LIGHTMAP:
8252                 dynamicvertex = true;
8253                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8254                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8255                 break;
8256         case Q3TCGEN_VECTOR:
8257                 dynamicvertex = true;
8258                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8259                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8260                 break;
8261         case Q3TCGEN_ENVIRONMENT:
8262                 dynamicvertex = true;
8263                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8264                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8265                 break;
8266         }
8267         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8268         {
8269                 dynamicvertex = true;
8270                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8271                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8272         }
8273
8274         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8275         {
8276                 dynamicvertex = true;
8277                 batchneed |= BATCHNEED_NOGAPS;
8278                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8279         }
8280
8281         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8282         {
8283                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8284                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8285                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8286                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8287                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8288                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8289                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8290         }
8291
8292         // when the model data has no vertex buffer (dynamic mesh), we need to
8293         // eliminate gaps
8294         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8295                 batchneed |= BATCHNEED_NOGAPS;
8296
8297         // if needsupdate, we have to do a dynamic vertex batch for sure
8298         if (needsupdate & batchneed)
8299                 dynamicvertex = true;
8300
8301         // see if we need to build vertexmesh from arrays
8302         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8303                 dynamicvertex = true;
8304
8305         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8306         // also some drivers strongly dislike firstvertex
8307         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8308                 dynamicvertex = true;
8309
8310         rsurface.batchvertex3f = rsurface.modelvertex3f;
8311         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8312         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8313         rsurface.batchsvector3f = rsurface.modelsvector3f;
8314         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8315         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8316         rsurface.batchtvector3f = rsurface.modeltvector3f;
8317         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8318         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8319         rsurface.batchnormal3f = rsurface.modelnormal3f;
8320         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8321         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8322         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8323         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8324         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8325         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8326         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8327         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8328         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8329         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8330         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8331         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8332         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8333         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8334         rsurface.batchelement3i = rsurface.modelelement3i;
8335         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8336         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8337         rsurface.batchelement3s = rsurface.modelelement3s;
8338         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8339         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8340
8341         // if any dynamic vertex processing has to occur in software, we copy the
8342         // entire surface list together before processing to rebase the vertices
8343         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8344         //
8345         // if any gaps exist and we do not have a static vertex buffer, we have to
8346         // copy the surface list together to avoid wasting upload bandwidth on the
8347         // vertices in the gaps.
8348         //
8349         // if gaps exist and we have a static vertex buffer, we still have to
8350         // combine the index buffer ranges into one dynamic index buffer.
8351         //
8352         // in all cases we end up with data that can be drawn in one call.
8353
8354         if (!dynamicvertex)
8355         {
8356                 // static vertex data, just set pointers...
8357                 rsurface.batchgeneratedvertex = false;
8358                 // if there are gaps, we want to build a combined index buffer,
8359                 // otherwise use the original static buffer with an appropriate offset
8360                 if (gaps)
8361                 {
8362                         // build a new triangle elements array for this batch
8363                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8364                         rsurface.batchfirsttriangle = 0;
8365                         numtriangles = 0;
8366                         for (i = 0;i < texturenumsurfaces;i++)
8367                         {
8368                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8369                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8370                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8371                                 numtriangles += surfacenumtriangles;
8372                         }
8373                         rsurface.batchelement3i_indexbuffer = NULL;
8374                         rsurface.batchelement3i_bufferoffset = 0;
8375                         rsurface.batchelement3s = NULL;
8376                         rsurface.batchelement3s_indexbuffer = NULL;
8377                         rsurface.batchelement3s_bufferoffset = 0;
8378                         if (endvertex <= 65536)
8379                         {
8380                                 // make a 16bit (unsigned short) index array if possible
8381                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8382                                 for (i = 0;i < numtriangles*3;i++)
8383                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8384                         }
8385                 }
8386                 return;
8387         }
8388
8389         // something needs software processing, do it for real...
8390         // we only directly handle separate array data in this case and then
8391         // generate interleaved data if needed...
8392         rsurface.batchgeneratedvertex = true;
8393
8394         // now copy the vertex data into a combined array and make an index array
8395         // (this is what Quake3 does all the time)
8396         //if (gaps || rsurface.batchfirstvertex)
8397         {
8398                 rsurface.batchvertex3fbuffer = NULL;
8399                 rsurface.batchvertexmesh = NULL;
8400                 rsurface.batchvertexmeshbuffer = NULL;
8401                 rsurface.batchvertex3f = NULL;
8402                 rsurface.batchvertex3f_vertexbuffer = NULL;
8403                 rsurface.batchvertex3f_bufferoffset = 0;
8404                 rsurface.batchsvector3f = NULL;
8405                 rsurface.batchsvector3f_vertexbuffer = NULL;
8406                 rsurface.batchsvector3f_bufferoffset = 0;
8407                 rsurface.batchtvector3f = NULL;
8408                 rsurface.batchtvector3f_vertexbuffer = NULL;
8409                 rsurface.batchtvector3f_bufferoffset = 0;
8410                 rsurface.batchnormal3f = NULL;
8411                 rsurface.batchnormal3f_vertexbuffer = NULL;
8412                 rsurface.batchnormal3f_bufferoffset = 0;
8413                 rsurface.batchlightmapcolor4f = NULL;
8414                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8415                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8416                 rsurface.batchtexcoordtexture2f = NULL;
8417                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8418                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8419                 rsurface.batchtexcoordlightmap2f = NULL;
8420                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8421                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8422                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8423                 rsurface.batchelement3i_indexbuffer = NULL;
8424                 rsurface.batchelement3i_bufferoffset = 0;
8425                 rsurface.batchelement3s = NULL;
8426                 rsurface.batchelement3s_indexbuffer = NULL;
8427                 rsurface.batchelement3s_bufferoffset = 0;
8428                 // we'll only be setting up certain arrays as needed
8429                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8430                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8431                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8432                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8433                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8434                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8435                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8436                 {
8437                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8438                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8439                 }
8440                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8441                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8442                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8443                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8444                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8445                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8446                 numvertices = 0;
8447                 numtriangles = 0;
8448                 for (i = 0;i < texturenumsurfaces;i++)
8449                 {
8450                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8451                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8452                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8453                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8454                         // copy only the data requested
8455                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8456                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8457                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8458                         {
8459                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8460                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8461                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8462                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8463                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8464                                 {
8465                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8466                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8467                                 }
8468                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8469                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8470                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8471                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8472                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8473                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8474                         }
8475                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8476                         numvertices += surfacenumvertices;
8477                         numtriangles += surfacenumtriangles;
8478                 }
8479
8480                 // generate a 16bit index array as well if possible
8481                 // (in general, dynamic batches fit)
8482                 if (numvertices <= 65536)
8483                 {
8484                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8485                         for (i = 0;i < numtriangles*3;i++)
8486                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8487                 }
8488
8489                 // since we've copied everything, the batch now starts at 0
8490                 rsurface.batchfirstvertex = 0;
8491                 rsurface.batchnumvertices = batchnumvertices;
8492                 rsurface.batchfirsttriangle = 0;
8493                 rsurface.batchnumtriangles = batchnumtriangles;
8494         }
8495
8496         // q1bsp surfaces rendered in vertex color mode have to have colors
8497         // calculated based on lightstyles
8498         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8499         {
8500                 // generate color arrays for the surfaces in this list
8501                 int c[4];
8502                 int scale;
8503                 int size3;
8504                 const int *offsets;
8505                 const unsigned char *lm;
8506                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8507                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8508                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8509                 numvertices = 0;
8510                 for (i = 0;i < texturenumsurfaces;i++)
8511                 {
8512                         surface = texturesurfacelist[i];
8513                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8514                         surfacenumvertices = surface->num_vertices;
8515                         if (surface->lightmapinfo->samples)
8516                         {
8517                                 for (j = 0;j < surfacenumvertices;j++)
8518                                 {
8519                                         lm = surface->lightmapinfo->samples + offsets[j];
8520                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8521                                         VectorScale(lm, scale, c);
8522                                         if (surface->lightmapinfo->styles[1] != 255)
8523                                         {
8524                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8525                                                 lm += size3;
8526                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8527                                                 VectorMA(c, scale, lm, c);
8528                                                 if (surface->lightmapinfo->styles[2] != 255)
8529                                                 {
8530                                                         lm += size3;
8531                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8532                                                         VectorMA(c, scale, lm, c);
8533                                                         if (surface->lightmapinfo->styles[3] != 255)
8534                                                         {
8535                                                                 lm += size3;
8536                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8537                                                                 VectorMA(c, scale, lm, c);
8538                                                         }
8539                                                 }
8540                                         }
8541                                         c[0] >>= 7;
8542                                         c[1] >>= 7;
8543                                         c[2] >>= 7;
8544                                         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);
8545                                         numvertices++;
8546                                 }
8547                         }
8548                         else
8549                         {
8550                                 for (j = 0;j < surfacenumvertices;j++)
8551                                 {
8552                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8553                                         numvertices++;
8554                                 }
8555                         }
8556                 }
8557         }
8558
8559         // if vertices are deformed (sprite flares and things in maps, possibly
8560         // water waves, bulges and other deformations), modify the copied vertices
8561         // in place
8562         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8563         {
8564                 switch (deform->deform)
8565                 {
8566                 default:
8567                 case Q3DEFORM_PROJECTIONSHADOW:
8568                 case Q3DEFORM_TEXT0:
8569                 case Q3DEFORM_TEXT1:
8570                 case Q3DEFORM_TEXT2:
8571                 case Q3DEFORM_TEXT3:
8572                 case Q3DEFORM_TEXT4:
8573                 case Q3DEFORM_TEXT5:
8574                 case Q3DEFORM_TEXT6:
8575                 case Q3DEFORM_TEXT7:
8576                 case Q3DEFORM_NONE:
8577                         break;
8578                 case Q3DEFORM_AUTOSPRITE:
8579                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8580                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8581                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8582                         VectorNormalize(newforward);
8583                         VectorNormalize(newright);
8584                         VectorNormalize(newup);
8585 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8586 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8587 //                      rsurface.batchvertex3f_bufferoffset = 0;
8588 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8589 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8590 //                      rsurface.batchsvector3f_bufferoffset = 0;
8591 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8592 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8593 //                      rsurface.batchtvector3f_bufferoffset = 0;
8594 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8595 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8596 //                      rsurface.batchnormal3f_bufferoffset = 0;
8597                         // a single autosprite surface can contain multiple sprites...
8598                         for (j = 0;j < batchnumvertices - 3;j += 4)
8599                         {
8600                                 VectorClear(center);
8601                                 for (i = 0;i < 4;i++)
8602                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8603                                 VectorScale(center, 0.25f, center);
8604                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8605                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8606                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8607                                 for (i = 0;i < 4;i++)
8608                                 {
8609                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8610                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8611                                 }
8612                         }
8613                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8614                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8615                         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);
8616                         break;
8617                 case Q3DEFORM_AUTOSPRITE2:
8618                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8619                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8620                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8621                         VectorNormalize(newforward);
8622                         VectorNormalize(newright);
8623                         VectorNormalize(newup);
8624 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8625 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8626 //                      rsurface.batchvertex3f_bufferoffset = 0;
8627                         {
8628                                 const float *v1, *v2;
8629                                 vec3_t start, end;
8630                                 float f, l;
8631                                 struct
8632                                 {
8633                                         float length2;
8634                                         const float *v1;
8635                                         const float *v2;
8636                                 }
8637                                 shortest[2];
8638                                 memset(shortest, 0, sizeof(shortest));
8639                                 // a single autosprite surface can contain multiple sprites...
8640                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8641                                 {
8642                                         VectorClear(center);
8643                                         for (i = 0;i < 4;i++)
8644                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8645                                         VectorScale(center, 0.25f, center);
8646                                         // find the two shortest edges, then use them to define the
8647                                         // axis vectors for rotating around the central axis
8648                                         for (i = 0;i < 6;i++)
8649                                         {
8650                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8651                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8652                                                 l = VectorDistance2(v1, v2);
8653                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8654                                                 if (v1[2] != v2[2])
8655                                                         l += (1.0f / 1024.0f);
8656                                                 if (shortest[0].length2 > l || i == 0)
8657                                                 {
8658                                                         shortest[1] = shortest[0];
8659                                                         shortest[0].length2 = l;
8660                                                         shortest[0].v1 = v1;
8661                                                         shortest[0].v2 = v2;
8662                                                 }
8663                                                 else if (shortest[1].length2 > l || i == 1)
8664                                                 {
8665                                                         shortest[1].length2 = l;
8666                                                         shortest[1].v1 = v1;
8667                                                         shortest[1].v2 = v2;
8668                                                 }
8669                                         }
8670                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8671                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8672                                         // this calculates the right vector from the shortest edge
8673                                         // and the up vector from the edge midpoints
8674                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8675                                         VectorNormalize(right);
8676                                         VectorSubtract(end, start, up);
8677                                         VectorNormalize(up);
8678                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8679                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8680                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8681                                         VectorNegate(forward, forward);
8682                                         VectorReflect(forward, 0, up, forward);
8683                                         VectorNormalize(forward);
8684                                         CrossProduct(up, forward, newright);
8685                                         VectorNormalize(newright);
8686                                         // rotate the quad around the up axis vector, this is made
8687                                         // especially easy by the fact we know the quad is flat,
8688                                         // so we only have to subtract the center position and
8689                                         // measure distance along the right vector, and then
8690                                         // multiply that by the newright vector and add back the
8691                                         // center position
8692                                         // we also need to subtract the old position to undo the
8693                                         // displacement from the center, which we do with a
8694                                         // DotProduct, the subtraction/addition of center is also
8695                                         // optimized into DotProducts here
8696                                         l = DotProduct(right, center);
8697                                         for (i = 0;i < 4;i++)
8698                                         {
8699                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8700                                                 f = DotProduct(right, v1) - l;
8701                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8702                                         }
8703                                 }
8704                         }
8705                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8706                         {
8707 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8708 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8709 //                              rsurface.batchnormal3f_bufferoffset = 0;
8710                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8711                         }
8712                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8713                         {
8714 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8715 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8716 //                              rsurface.batchsvector3f_bufferoffset = 0;
8717 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8718 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8719 //                              rsurface.batchtvector3f_bufferoffset = 0;
8720                                 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);
8721                         }
8722                         break;
8723                 case Q3DEFORM_NORMAL:
8724                         // deform the normals to make reflections wavey
8725                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8726                         rsurface.batchnormal3f_vertexbuffer = NULL;
8727                         rsurface.batchnormal3f_bufferoffset = 0;
8728                         for (j = 0;j < batchnumvertices;j++)
8729                         {
8730                                 float vertex[3];
8731                                 float *normal = rsurface.batchnormal3f + 3*j;
8732                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8733                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8734                                 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]);
8735                                 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]);
8736                                 VectorNormalize(normal);
8737                         }
8738                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8739                         {
8740 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8741 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8742 //                              rsurface.batchsvector3f_bufferoffset = 0;
8743 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8744 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8745 //                              rsurface.batchtvector3f_bufferoffset = 0;
8746                                 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);
8747                         }
8748                         break;
8749                 case Q3DEFORM_WAVE:
8750                         // deform vertex array to make wavey water and flags and such
8751                         waveparms[0] = deform->waveparms[0];
8752                         waveparms[1] = deform->waveparms[1];
8753                         waveparms[2] = deform->waveparms[2];
8754                         waveparms[3] = deform->waveparms[3];
8755                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8756                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8757                         // this is how a divisor of vertex influence on deformation
8758                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8759                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8760 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8761 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8762 //                      rsurface.batchvertex3f_bufferoffset = 0;
8763 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8764 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8765 //                      rsurface.batchnormal3f_bufferoffset = 0;
8766                         for (j = 0;j < batchnumvertices;j++)
8767                         {
8768                                 // if the wavefunc depends on time, evaluate it per-vertex
8769                                 if (waveparms[3])
8770                                 {
8771                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8772                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8773                                 }
8774                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8775                         }
8776                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8777                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8778                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8779                         {
8780 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8781 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8782 //                              rsurface.batchsvector3f_bufferoffset = 0;
8783 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8784 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8785 //                              rsurface.batchtvector3f_bufferoffset = 0;
8786                                 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);
8787                         }
8788                         break;
8789                 case Q3DEFORM_BULGE:
8790                         // deform vertex array to make the surface have moving bulges
8791 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8792 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8793 //                      rsurface.batchvertex3f_bufferoffset = 0;
8794 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8795 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8796 //                      rsurface.batchnormal3f_bufferoffset = 0;
8797                         for (j = 0;j < batchnumvertices;j++)
8798                         {
8799                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8800                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8801                         }
8802                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8803                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8804                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8805                         {
8806 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8807 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8808 //                              rsurface.batchsvector3f_bufferoffset = 0;
8809 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8810 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8811 //                              rsurface.batchtvector3f_bufferoffset = 0;
8812                                 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);
8813                         }
8814                         break;
8815                 case Q3DEFORM_MOVE:
8816                         // deform vertex array
8817                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8818                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8819                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8820                         VectorScale(deform->parms, scale, waveparms);
8821 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8822 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8823 //                      rsurface.batchvertex3f_bufferoffset = 0;
8824                         for (j = 0;j < batchnumvertices;j++)
8825                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8826                         break;
8827                 }
8828         }
8829
8830         // generate texcoords based on the chosen texcoord source
8831         switch(rsurface.texture->tcgen.tcgen)
8832         {
8833         default:
8834         case Q3TCGEN_TEXTURE:
8835                 break;
8836         case Q3TCGEN_LIGHTMAP:
8837 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8838 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8839 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8840                 if (rsurface.batchtexcoordlightmap2f)
8841                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8842                 break;
8843         case Q3TCGEN_VECTOR:
8844 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8845 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8846 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8847                 for (j = 0;j < batchnumvertices;j++)
8848                 {
8849                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8850                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8851                 }
8852                 break;
8853         case Q3TCGEN_ENVIRONMENT:
8854                 // make environment reflections using a spheremap
8855                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8856                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8857                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8858                 for (j = 0;j < batchnumvertices;j++)
8859                 {
8860                         // identical to Q3A's method, but executed in worldspace so
8861                         // carried models can be shiny too
8862
8863                         float viewer[3], d, reflected[3], worldreflected[3];
8864
8865                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8866                         // VectorNormalize(viewer);
8867
8868                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8869
8870                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8871                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8872                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8873                         // note: this is proportinal to viewer, so we can normalize later
8874
8875                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8876                         VectorNormalize(worldreflected);
8877
8878                         // note: this sphere map only uses world x and z!
8879                         // so positive and negative y will LOOK THE SAME.
8880                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8881                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8882                 }
8883                 break;
8884         }
8885         // the only tcmod that needs software vertex processing is turbulent, so
8886         // check for it here and apply the changes if needed
8887         // and we only support that as the first one
8888         // (handling a mixture of turbulent and other tcmods would be problematic
8889         //  without punting it entirely to a software path)
8890         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8891         {
8892                 amplitude = rsurface.texture->tcmods[0].parms[1];
8893                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8894 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8895 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8896 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8897                 for (j = 0;j < batchnumvertices;j++)
8898                 {
8899                         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);
8900                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8901                 }
8902         }
8903
8904         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8905         {
8906                 // convert the modified arrays to vertex structs
8907 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8908 //              rsurface.batchvertexmeshbuffer = NULL;
8909                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8910                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8911                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8912                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8913                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8914                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8915                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8916                 {
8917                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8918                         {
8919                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8920                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8921                         }
8922                 }
8923                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8924                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8925                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8926                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8927                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8928                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8929                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8930                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8931                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8932         }
8933 }
8934
8935 void RSurf_DrawBatch(void)
8936 {
8937         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8938         // through the pipeline, killing it earlier in the pipeline would have
8939         // per-surface overhead rather than per-batch overhead, so it's best to
8940         // reject it here, before it hits glDraw.
8941         if (rsurface.batchnumtriangles == 0)
8942                 return;
8943 #if 0
8944         // batch debugging code
8945         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8946         {
8947                 int i;
8948                 int j;
8949                 int c;
8950                 const int *e;
8951                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8952                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8953                 {
8954                         c = e[i];
8955                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8956                         {
8957                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8958                                 {
8959                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8960                                                 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);
8961                                         break;
8962                                 }
8963                         }
8964                 }
8965         }
8966 #endif
8967         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);
8968 }
8969
8970 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8971 {
8972         // pick the closest matching water plane
8973         int planeindex, vertexindex, bestplaneindex = -1;
8974         float d, bestd;
8975         vec3_t vert;
8976         const float *v;
8977         r_waterstate_waterplane_t *p;
8978         qboolean prepared = false;
8979         bestd = 0;
8980         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8981         {
8982                 if(p->camera_entity != rsurface.texture->camera_entity)
8983                         continue;
8984                 d = 0;
8985                 if(!prepared)
8986                 {
8987                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8988                         prepared = true;
8989                         if(rsurface.batchnumvertices == 0)
8990                                 break;
8991                 }
8992                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8993                 {
8994                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8995                         d += fabs(PlaneDiff(vert, &p->plane));
8996                 }
8997                 if (bestd > d || bestplaneindex < 0)
8998                 {
8999                         bestd = d;
9000                         bestplaneindex = planeindex;
9001                 }
9002         }
9003         return bestplaneindex;
9004         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9005         // this situation though, as it might be better to render single larger
9006         // batches with useless stuff (backface culled for example) than to
9007         // render multiple smaller batches
9008 }
9009
9010 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9011 {
9012         int i;
9013         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9014         rsurface.passcolor4f_vertexbuffer = 0;
9015         rsurface.passcolor4f_bufferoffset = 0;
9016         for (i = 0;i < rsurface.batchnumvertices;i++)
9017                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9018 }
9019
9020 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9021 {
9022         int i;
9023         float f;
9024         const float *v;
9025         const float *c;
9026         float *c2;
9027         if (rsurface.passcolor4f)
9028         {
9029                 // generate color arrays
9030                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9031                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9032                 rsurface.passcolor4f_vertexbuffer = 0;
9033                 rsurface.passcolor4f_bufferoffset = 0;
9034                 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)
9035                 {
9036                         f = RSurf_FogVertex(v);
9037                         c2[0] = c[0] * f;
9038                         c2[1] = c[1] * f;
9039                         c2[2] = c[2] * f;
9040                         c2[3] = c[3];
9041                 }
9042         }
9043         else
9044         {
9045                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9046                 rsurface.passcolor4f_vertexbuffer = 0;
9047                 rsurface.passcolor4f_bufferoffset = 0;
9048                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9049                 {
9050                         f = RSurf_FogVertex(v);
9051                         c2[0] = f;
9052                         c2[1] = f;
9053                         c2[2] = f;
9054                         c2[3] = 1;
9055                 }
9056         }
9057 }
9058
9059 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9060 {
9061         int i;
9062         float f;
9063         const float *v;
9064         const float *c;
9065         float *c2;
9066         if (!rsurface.passcolor4f)
9067                 return;
9068         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9069         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9070         rsurface.passcolor4f_vertexbuffer = 0;
9071         rsurface.passcolor4f_bufferoffset = 0;
9072         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)
9073         {
9074                 f = RSurf_FogVertex(v);
9075                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9076                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9077                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9078                 c2[3] = c[3];
9079         }
9080 }
9081
9082 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9083 {
9084         int i;
9085         const float *c;
9086         float *c2;
9087         if (!rsurface.passcolor4f)
9088                 return;
9089         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9090         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9091         rsurface.passcolor4f_vertexbuffer = 0;
9092         rsurface.passcolor4f_bufferoffset = 0;
9093         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9094         {
9095                 c2[0] = c[0] * r;
9096                 c2[1] = c[1] * g;
9097                 c2[2] = c[2] * b;
9098                 c2[3] = c[3] * a;
9099         }
9100 }
9101
9102 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9103 {
9104         int i;
9105         const float *c;
9106         float *c2;
9107         if (!rsurface.passcolor4f)
9108                 return;
9109         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9110         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9111         rsurface.passcolor4f_vertexbuffer = 0;
9112         rsurface.passcolor4f_bufferoffset = 0;
9113         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9114         {
9115                 c2[0] = c[0] + r_refdef.scene.ambient;
9116                 c2[1] = c[1] + r_refdef.scene.ambient;
9117                 c2[2] = c[2] + r_refdef.scene.ambient;
9118                 c2[3] = c[3];
9119         }
9120 }
9121
9122 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9123 {
9124         // TODO: optimize
9125         rsurface.passcolor4f = NULL;
9126         rsurface.passcolor4f_vertexbuffer = 0;
9127         rsurface.passcolor4f_bufferoffset = 0;
9128         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9129         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9130         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9131         GL_Color(r, g, b, a);
9132         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9133         RSurf_DrawBatch();
9134 }
9135
9136 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9137 {
9138         // TODO: optimize applyfog && applycolor case
9139         // just apply fog if necessary, and tint the fog color array if necessary
9140         rsurface.passcolor4f = NULL;
9141         rsurface.passcolor4f_vertexbuffer = 0;
9142         rsurface.passcolor4f_bufferoffset = 0;
9143         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9144         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9145         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9146         GL_Color(r, g, b, a);
9147         RSurf_DrawBatch();
9148 }
9149
9150 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9151 {
9152         // TODO: optimize
9153         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9154         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9155         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9156         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9157         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9158         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9159         GL_Color(r, g, b, a);
9160         RSurf_DrawBatch();
9161 }
9162
9163 static void RSurf_DrawBatch_GL11_ClampColor(void)
9164 {
9165         int i;
9166         const float *c1;
9167         float *c2;
9168         if (!rsurface.passcolor4f)
9169                 return;
9170         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9171         {
9172                 c2[0] = bound(0.0f, c1[0], 1.0f);
9173                 c2[1] = bound(0.0f, c1[1], 1.0f);
9174                 c2[2] = bound(0.0f, c1[2], 1.0f);
9175                 c2[3] = bound(0.0f, c1[3], 1.0f);
9176         }
9177 }
9178
9179 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9180 {
9181         int i;
9182         float f;
9183         const float *v;
9184         const float *n;
9185         float *c;
9186         //vec3_t eyedir;
9187
9188         // fake shading
9189         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9190         rsurface.passcolor4f_vertexbuffer = 0;
9191         rsurface.passcolor4f_bufferoffset = 0;
9192         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)
9193         {
9194                 f = -DotProduct(r_refdef.view.forward, n);
9195                 f = max(0, f);
9196                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9197                 f *= r_refdef.lightmapintensity;
9198                 Vector4Set(c, f, f, f, 1);
9199         }
9200 }
9201
9202 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9203 {
9204         RSurf_DrawBatch_GL11_ApplyFakeLight();
9205         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9206         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9207         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9208         GL_Color(r, g, b, a);
9209         RSurf_DrawBatch();
9210 }
9211
9212 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9213 {
9214         int i;
9215         float f;
9216         float alpha;
9217         const float *v;
9218         const float *n;
9219         float *c;
9220         vec3_t ambientcolor;
9221         vec3_t diffusecolor;
9222         vec3_t lightdir;
9223         // TODO: optimize
9224         // model lighting
9225         VectorCopy(rsurface.modellight_lightdir, lightdir);
9226         f = 0.5f * r_refdef.lightmapintensity;
9227         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9228         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9229         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9230         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9231         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9232         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9233         alpha = *a;
9234         if (VectorLength2(diffusecolor) > 0)
9235         {
9236                 // q3-style directional shading
9237                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9238                 rsurface.passcolor4f_vertexbuffer = 0;
9239                 rsurface.passcolor4f_bufferoffset = 0;
9240                 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)
9241                 {
9242                         if ((f = DotProduct(n, lightdir)) > 0)
9243                                 VectorMA(ambientcolor, f, diffusecolor, c);
9244                         else
9245                                 VectorCopy(ambientcolor, c);
9246                         c[3] = alpha;
9247                 }
9248                 *r = 1;
9249                 *g = 1;
9250                 *b = 1;
9251                 *a = 1;
9252                 *applycolor = false;
9253         }
9254         else
9255         {
9256                 *r = ambientcolor[0];
9257                 *g = ambientcolor[1];
9258                 *b = ambientcolor[2];
9259                 rsurface.passcolor4f = NULL;
9260                 rsurface.passcolor4f_vertexbuffer = 0;
9261                 rsurface.passcolor4f_bufferoffset = 0;
9262         }
9263 }
9264
9265 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9266 {
9267         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9268         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9269         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9270         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9271         GL_Color(r, g, b, a);
9272         RSurf_DrawBatch();
9273 }
9274
9275 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9276 {
9277         int i;
9278         float f;
9279         const float *v;
9280         float *c;
9281
9282         // fake shading
9283         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9284         rsurface.passcolor4f_vertexbuffer = 0;
9285         rsurface.passcolor4f_bufferoffset = 0;
9286
9287         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9288         {
9289                 f = 1 - RSurf_FogVertex(v);
9290                 c[0] = r;
9291                 c[1] = g;
9292                 c[2] = b;
9293                 c[3] = f * a;
9294         }
9295 }
9296
9297 void RSurf_SetupDepthAndCulling(void)
9298 {
9299         // submodels are biased to avoid z-fighting with world surfaces that they
9300         // may be exactly overlapping (avoids z-fighting artifacts on certain
9301         // doors and things in Quake maps)
9302         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9303         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9304         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9305         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9306 }
9307
9308 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9309 {
9310         // transparent sky would be ridiculous
9311         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9312                 return;
9313         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9314         skyrenderlater = true;
9315         RSurf_SetupDepthAndCulling();
9316         GL_DepthMask(true);
9317         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9318         // skymasking on them, and Quake3 never did sky masking (unlike
9319         // software Quake and software Quake2), so disable the sky masking
9320         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9321         // and skymasking also looks very bad when noclipping outside the
9322         // level, so don't use it then either.
9323         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9324         {
9325                 R_Mesh_ResetTextureState();
9326                 if (skyrendermasked)
9327                 {
9328                         R_SetupShader_DepthOrShadow();
9329                         // depth-only (masking)
9330                         GL_ColorMask(0,0,0,0);
9331                         // just to make sure that braindead drivers don't draw
9332                         // anything despite that colormask...
9333                         GL_BlendFunc(GL_ZERO, GL_ONE);
9334                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9335                         if (rsurface.batchvertex3fbuffer)
9336                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9337                         else
9338                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9339                 }
9340                 else
9341                 {
9342                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9343                         // fog sky
9344                         GL_BlendFunc(GL_ONE, GL_ZERO);
9345                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9346                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9347                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9348                 }
9349                 RSurf_DrawBatch();
9350                 if (skyrendermasked)
9351                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9352         }
9353         R_Mesh_ResetTextureState();
9354         GL_Color(1, 1, 1, 1);
9355 }
9356
9357 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9358 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9359 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9360 {
9361         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9362                 return;
9363         if (prepass)
9364         {
9365                 // render screenspace normalmap to texture
9366                 GL_DepthMask(true);
9367                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9368                 RSurf_DrawBatch();
9369                 return;
9370         }
9371
9372         // bind lightmap texture
9373
9374         // water/refraction/reflection/camera surfaces have to be handled specially
9375         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9376         {
9377                 int start, end, startplaneindex;
9378                 for (start = 0;start < texturenumsurfaces;start = end)
9379                 {
9380                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9381                         if(startplaneindex < 0)
9382                         {
9383                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9384                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9385                                 end = start + 1;
9386                                 continue;
9387                         }
9388                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9389                                 ;
9390                         // now that we have a batch using the same planeindex, render it
9391                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9392                         {
9393                                 // render water or distortion background
9394                                 GL_DepthMask(true);
9395                                 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));
9396                                 RSurf_DrawBatch();
9397                                 // blend surface on top
9398                                 GL_DepthMask(false);
9399                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9400                                 RSurf_DrawBatch();
9401                         }
9402                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9403                         {
9404                                 // render surface with reflection texture as input
9405                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9406                                 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));
9407                                 RSurf_DrawBatch();
9408                         }
9409                 }
9410                 return;
9411         }
9412
9413         // render surface batch normally
9414         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9415         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9416         RSurf_DrawBatch();
9417 }
9418
9419 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9420 {
9421         // OpenGL 1.3 path - anything not completely ancient
9422         qboolean applycolor;
9423         qboolean applyfog;
9424         int layerindex;
9425         const texturelayer_t *layer;
9426         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);
9427         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9428
9429         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9430         {
9431                 vec4_t layercolor;
9432                 int layertexrgbscale;
9433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9434                 {
9435                         if (layerindex == 0)
9436                                 GL_AlphaTest(true);
9437                         else
9438                         {
9439                                 GL_AlphaTest(false);
9440                                 GL_DepthFunc(GL_EQUAL);
9441                         }
9442                 }
9443                 GL_DepthMask(layer->depthmask && writedepth);
9444                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9445                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9446                 {
9447                         layertexrgbscale = 4;
9448                         VectorScale(layer->color, 0.25f, layercolor);
9449                 }
9450                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9451                 {
9452                         layertexrgbscale = 2;
9453                         VectorScale(layer->color, 0.5f, layercolor);
9454                 }
9455                 else
9456                 {
9457                         layertexrgbscale = 1;
9458                         VectorScale(layer->color, 1.0f, layercolor);
9459                 }
9460                 layercolor[3] = layer->color[3];
9461                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9462                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9463                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9464                 switch (layer->type)
9465                 {
9466                 case TEXTURELAYERTYPE_LITTEXTURE:
9467                         // single-pass lightmapped texture with 2x rgbscale
9468                         R_Mesh_TexBind(0, r_texture_white);
9469                         R_Mesh_TexMatrix(0, NULL);
9470                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9471                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9472                         R_Mesh_TexBind(1, layer->texture);
9473                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9474                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9475                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9476                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9477                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9478                         else if (FAKELIGHT_ENABLED)
9479                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9480                         else if (rsurface.uselightmaptexture)
9481                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9482                         else
9483                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9484                         break;
9485                 case TEXTURELAYERTYPE_TEXTURE:
9486                         // singletexture unlit texture with transparency support
9487                         R_Mesh_TexBind(0, layer->texture);
9488                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9489                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9490                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9491                         R_Mesh_TexBind(1, 0);
9492                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9493                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9494                         break;
9495                 case TEXTURELAYERTYPE_FOG:
9496                         // singletexture fogging
9497                         if (layer->texture)
9498                         {
9499                                 R_Mesh_TexBind(0, layer->texture);
9500                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9501                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9502                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9503                         }
9504                         else
9505                         {
9506                                 R_Mesh_TexBind(0, 0);
9507                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9508                         }
9509                         R_Mesh_TexBind(1, 0);
9510                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9511                         // generate a color array for the fog pass
9512                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9513                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9514                         RSurf_DrawBatch();
9515                         break;
9516                 default:
9517                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9518                 }
9519         }
9520         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9521         {
9522                 GL_DepthFunc(GL_LEQUAL);
9523                 GL_AlphaTest(false);
9524         }
9525 }
9526
9527 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9528 {
9529         // OpenGL 1.1 - crusty old voodoo path
9530         qboolean applyfog;
9531         int layerindex;
9532         const texturelayer_t *layer;
9533         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);
9534         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9535
9536         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9537         {
9538                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9539                 {
9540                         if (layerindex == 0)
9541                                 GL_AlphaTest(true);
9542                         else
9543                         {
9544                                 GL_AlphaTest(false);
9545                                 GL_DepthFunc(GL_EQUAL);
9546                         }
9547                 }
9548                 GL_DepthMask(layer->depthmask && writedepth);
9549                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9550                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9551                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9552                 switch (layer->type)
9553                 {
9554                 case TEXTURELAYERTYPE_LITTEXTURE:
9555                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9556                         {
9557                                 // two-pass lit texture with 2x rgbscale
9558                                 // first the lightmap pass
9559                                 R_Mesh_TexBind(0, r_texture_white);
9560                                 R_Mesh_TexMatrix(0, NULL);
9561                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9562                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9563                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9564                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9565                                 else if (FAKELIGHT_ENABLED)
9566                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9567                                 else if (rsurface.uselightmaptexture)
9568                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9569                                 else
9570                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9571                                 // then apply the texture to it
9572                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9573                                 R_Mesh_TexBind(0, layer->texture);
9574                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9575                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9576                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9577                                 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);
9578                         }
9579                         else
9580                         {
9581                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9582                                 R_Mesh_TexBind(0, layer->texture);
9583                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9584                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9585                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9586                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9587                                         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);
9588                                 else
9589                                         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);
9590                         }
9591                         break;
9592                 case TEXTURELAYERTYPE_TEXTURE:
9593                         // singletexture unlit texture with transparency support
9594                         R_Mesh_TexBind(0, layer->texture);
9595                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9596                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9597                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9598                         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);
9599                         break;
9600                 case TEXTURELAYERTYPE_FOG:
9601                         // singletexture fogging
9602                         if (layer->texture)
9603                         {
9604                                 R_Mesh_TexBind(0, layer->texture);
9605                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9606                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9607                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9608                         }
9609                         else
9610                         {
9611                                 R_Mesh_TexBind(0, 0);
9612                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9613                         }
9614                         // generate a color array for the fog pass
9615                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9616                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9617                         RSurf_DrawBatch();
9618                         break;
9619                 default:
9620                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9621                 }
9622         }
9623         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9624         {
9625                 GL_DepthFunc(GL_LEQUAL);
9626                 GL_AlphaTest(false);
9627         }
9628 }
9629
9630 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9631 {
9632         int vi;
9633         int j;
9634         r_vertexgeneric_t *batchvertex;
9635         float c[4];
9636
9637 //      R_Mesh_ResetTextureState();
9638         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9639
9640         if(rsurface.texture && rsurface.texture->currentskinframe)
9641         {
9642                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9643                 c[3] *= rsurface.texture->currentalpha;
9644         }
9645         else
9646         {
9647                 c[0] = 1;
9648                 c[1] = 0;
9649                 c[2] = 1;
9650                 c[3] = 1;
9651         }
9652
9653         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9654         {
9655                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9656                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9657                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9658         }
9659
9660         // brighten it up (as texture value 127 means "unlit")
9661         c[0] *= 2 * r_refdef.view.colorscale;
9662         c[1] *= 2 * r_refdef.view.colorscale;
9663         c[2] *= 2 * r_refdef.view.colorscale;
9664
9665         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9666                 c[3] *= r_wateralpha.value;
9667
9668         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9669         {
9670                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9671                 GL_DepthMask(false);
9672         }
9673         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9674         {
9675                 GL_BlendFunc(GL_ONE, GL_ONE);
9676                 GL_DepthMask(false);
9677         }
9678         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9679         {
9680                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9681                 GL_DepthMask(false);
9682         }
9683         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9684         {
9685                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9686                 GL_DepthMask(false);
9687         }
9688         else
9689         {
9690                 GL_BlendFunc(GL_ONE, GL_ZERO);
9691                 GL_DepthMask(writedepth);
9692         }
9693
9694         if (r_showsurfaces.integer == 3)
9695         {
9696                 rsurface.passcolor4f = NULL;
9697
9698                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9699                 {
9700                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9701
9702                         rsurface.passcolor4f = NULL;
9703                         rsurface.passcolor4f_vertexbuffer = 0;
9704                         rsurface.passcolor4f_bufferoffset = 0;
9705                 }
9706                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9707                 {
9708                         qboolean applycolor = true;
9709                         float one = 1.0;
9710
9711                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9712
9713                         r_refdef.lightmapintensity = 1;
9714                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9715                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9716                 }
9717                 else if (FAKELIGHT_ENABLED)
9718                 {
9719                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9720
9721                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9722                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9723                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9724                 }
9725                 else
9726                 {
9727                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9728
9729                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9730                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9731                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9732                 }
9733
9734                 if(!rsurface.passcolor4f)
9735                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9736
9737                 RSurf_DrawBatch_GL11_ApplyAmbient();
9738                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9739                 if(r_refdef.fogenabled)
9740                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9741                 RSurf_DrawBatch_GL11_ClampColor();
9742
9743                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9744                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9745                 RSurf_DrawBatch();
9746         }
9747         else if (!r_refdef.view.showdebug)
9748         {
9749                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9750                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9751                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9752                 {
9753                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9754                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9755                 }
9756                 R_Mesh_PrepareVertices_Generic_Unlock();
9757                 RSurf_DrawBatch();
9758         }
9759         else if (r_showsurfaces.integer == 4)
9760         {
9761                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9762                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9763                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9764                 {
9765                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9766                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9767                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9768                 }
9769                 R_Mesh_PrepareVertices_Generic_Unlock();
9770                 RSurf_DrawBatch();
9771         }
9772         else if (r_showsurfaces.integer == 2)
9773         {
9774                 const int *e;
9775                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9776                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9777                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9778                 {
9779                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9780                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9781                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9782                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9783                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9784                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9785                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9786                 }
9787                 R_Mesh_PrepareVertices_Generic_Unlock();
9788                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9789         }
9790         else
9791         {
9792                 int texturesurfaceindex;
9793                 int k;
9794                 const msurface_t *surface;
9795                 float surfacecolor4f[4];
9796                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9797                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9798                 vi = 0;
9799                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9800                 {
9801                         surface = texturesurfacelist[texturesurfaceindex];
9802                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9803                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9804                         for (j = 0;j < surface->num_vertices;j++)
9805                         {
9806                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9807                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9808                                 vi++;
9809                         }
9810                 }
9811                 R_Mesh_PrepareVertices_Generic_Unlock();
9812                 RSurf_DrawBatch();
9813         }
9814 }
9815
9816 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9817 {
9818         CHECKGLERROR
9819         RSurf_SetupDepthAndCulling();
9820         if (r_showsurfaces.integer)
9821         {
9822                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9823                 return;
9824         }
9825         switch (vid.renderpath)
9826         {
9827         case RENDERPATH_GL20:
9828         case RENDERPATH_D3D9:
9829         case RENDERPATH_D3D10:
9830         case RENDERPATH_D3D11:
9831         case RENDERPATH_SOFT:
9832         case RENDERPATH_GLES2:
9833                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9834                 break;
9835         case RENDERPATH_GL13:
9836                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9837                 break;
9838         case RENDERPATH_GL11:
9839                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9840                 break;
9841         }
9842         CHECKGLERROR
9843 }
9844
9845 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9846 {
9847         CHECKGLERROR
9848         RSurf_SetupDepthAndCulling();
9849         if (r_showsurfaces.integer)
9850         {
9851                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9852                 return;
9853         }
9854         switch (vid.renderpath)
9855         {
9856         case RENDERPATH_GL20:
9857         case RENDERPATH_D3D9:
9858         case RENDERPATH_D3D10:
9859         case RENDERPATH_D3D11:
9860         case RENDERPATH_SOFT:
9861         case RENDERPATH_GLES2:
9862                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9863                 break;
9864         case RENDERPATH_GL13:
9865                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9866                 break;
9867         case RENDERPATH_GL11:
9868                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9869                 break;
9870         }
9871         CHECKGLERROR
9872 }
9873
9874 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9875 {
9876         int i, j;
9877         int texturenumsurfaces, endsurface;
9878         texture_t *texture;
9879         const msurface_t *surface;
9880 #define MAXBATCH_TRANSPARENTSURFACES 256
9881         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9882
9883         // if the model is static it doesn't matter what value we give for
9884         // wantnormals and wanttangents, so this logic uses only rules applicable
9885         // to a model, knowing that they are meaningless otherwise
9886         if (ent == r_refdef.scene.worldentity)
9887                 RSurf_ActiveWorldEntity();
9888         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9889                 RSurf_ActiveModelEntity(ent, false, false, false);
9890         else
9891         {
9892                 switch (vid.renderpath)
9893                 {
9894                 case RENDERPATH_GL20:
9895                 case RENDERPATH_D3D9:
9896                 case RENDERPATH_D3D10:
9897                 case RENDERPATH_D3D11:
9898                 case RENDERPATH_SOFT:
9899                 case RENDERPATH_GLES2:
9900                         RSurf_ActiveModelEntity(ent, true, true, false);
9901                         break;
9902                 case RENDERPATH_GL13:
9903                 case RENDERPATH_GL11:
9904                         RSurf_ActiveModelEntity(ent, true, false, false);
9905                         break;
9906                 }
9907         }
9908
9909         if (r_transparentdepthmasking.integer)
9910         {
9911                 qboolean setup = false;
9912                 for (i = 0;i < numsurfaces;i = j)
9913                 {
9914                         j = i + 1;
9915                         surface = rsurface.modelsurfaces + surfacelist[i];
9916                         texture = surface->texture;
9917                         rsurface.texture = R_GetCurrentTexture(texture);
9918                         rsurface.lightmaptexture = NULL;
9919                         rsurface.deluxemaptexture = NULL;
9920                         rsurface.uselightmaptexture = false;
9921                         // scan ahead until we find a different texture
9922                         endsurface = min(i + 1024, numsurfaces);
9923                         texturenumsurfaces = 0;
9924                         texturesurfacelist[texturenumsurfaces++] = surface;
9925                         for (;j < endsurface;j++)
9926                         {
9927                                 surface = rsurface.modelsurfaces + surfacelist[j];
9928                                 if (texture != surface->texture)
9929                                         break;
9930                                 texturesurfacelist[texturenumsurfaces++] = surface;
9931                         }
9932                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9933                                 continue;
9934                         // render the range of surfaces as depth
9935                         if (!setup)
9936                         {
9937                                 setup = true;
9938                                 GL_ColorMask(0,0,0,0);
9939                                 GL_Color(1,1,1,1);
9940                                 GL_DepthTest(true);
9941                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9942                                 GL_DepthMask(true);
9943 //                              R_Mesh_ResetTextureState();
9944                                 R_SetupShader_DepthOrShadow();
9945                         }
9946                         RSurf_SetupDepthAndCulling();
9947                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9948                         if (rsurface.batchvertex3fbuffer)
9949                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9950                         else
9951                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9952                         RSurf_DrawBatch();
9953                 }
9954                 if (setup)
9955                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9956         }
9957
9958         for (i = 0;i < numsurfaces;i = j)
9959         {
9960                 j = i + 1;
9961                 surface = rsurface.modelsurfaces + surfacelist[i];
9962                 texture = surface->texture;
9963                 rsurface.texture = R_GetCurrentTexture(texture);
9964                 // scan ahead until we find a different texture
9965                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9966                 texturenumsurfaces = 0;
9967                 texturesurfacelist[texturenumsurfaces++] = surface;
9968                 if(FAKELIGHT_ENABLED)
9969                 {
9970                         rsurface.lightmaptexture = NULL;
9971                         rsurface.deluxemaptexture = NULL;
9972                         rsurface.uselightmaptexture = false;
9973                         for (;j < endsurface;j++)
9974                         {
9975                                 surface = rsurface.modelsurfaces + surfacelist[j];
9976                                 if (texture != surface->texture)
9977                                         break;
9978                                 texturesurfacelist[texturenumsurfaces++] = surface;
9979                         }
9980                 }
9981                 else
9982                 {
9983                         rsurface.lightmaptexture = surface->lightmaptexture;
9984                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9985                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9986                         for (;j < endsurface;j++)
9987                         {
9988                                 surface = rsurface.modelsurfaces + surfacelist[j];
9989                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9990                                         break;
9991                                 texturesurfacelist[texturenumsurfaces++] = surface;
9992                         }
9993                 }
9994                 // render the range of surfaces
9995                 if (ent == r_refdef.scene.worldentity)
9996                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9997                 else
9998                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9999         }
10000         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10001 }
10002
10003 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10004 {
10005         // transparent surfaces get pushed off into the transparent queue
10006         int surfacelistindex;
10007         const msurface_t *surface;
10008         vec3_t tempcenter, center;
10009         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10010         {
10011                 surface = texturesurfacelist[surfacelistindex];
10012                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10013                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10014                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10015                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10016                 if (queueentity->transparent_offset) // transparent offset
10017                 {
10018                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10019                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10020                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10021                 }
10022                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10023         }
10024 }
10025
10026 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10027 {
10028         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10029                 return;
10030         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10031                 return;
10032         RSurf_SetupDepthAndCulling();
10033         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10034         if (rsurface.batchvertex3fbuffer)
10035                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10036         else
10037                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10038         RSurf_DrawBatch();
10039 }
10040
10041 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10042 {
10043         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10044         CHECKGLERROR
10045         if (depthonly)
10046                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10047         else if (prepass)
10048         {
10049                 if (!rsurface.texture->currentnumlayers)
10050                         return;
10051                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10052                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10053                 else
10054                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10055         }
10056         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10057                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10058         else if (!rsurface.texture->currentnumlayers)
10059                 return;
10060         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10061         {
10062                 // in the deferred case, transparent surfaces were queued during prepass
10063                 if (!r_shadow_usingdeferredprepass)
10064                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10065         }
10066         else
10067         {
10068                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10069                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10070         }
10071         CHECKGLERROR
10072 }
10073
10074 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10075 {
10076         int i, j;
10077         texture_t *texture;
10078         R_FrameData_SetMark();
10079         // break the surface list down into batches by texture and use of lightmapping
10080         for (i = 0;i < numsurfaces;i = j)
10081         {
10082                 j = i + 1;
10083                 // texture is the base texture pointer, rsurface.texture is the
10084                 // current frame/skin the texture is directing us to use (for example
10085                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10086                 // use skin 1 instead)
10087                 texture = surfacelist[i]->texture;
10088                 rsurface.texture = R_GetCurrentTexture(texture);
10089                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10090                 {
10091                         // if this texture is not the kind we want, skip ahead to the next one
10092                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10093                                 ;
10094                         continue;
10095                 }
10096                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10097                 {
10098                         rsurface.lightmaptexture = NULL;
10099                         rsurface.deluxemaptexture = NULL;
10100                         rsurface.uselightmaptexture = false;
10101                         // simply scan ahead until we find a different texture or lightmap state
10102                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10103                                 ;
10104                 }
10105                 else
10106                 {
10107                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10108                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10109                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10110                         // simply scan ahead until we find a different texture or lightmap state
10111                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10112                                 ;
10113                 }
10114                 // render the range of surfaces
10115                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10116         }
10117         R_FrameData_ReturnToMark();
10118 }
10119
10120 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10121 {
10122         CHECKGLERROR
10123         if (depthonly)
10124                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10125         else if (prepass)
10126         {
10127                 if (!rsurface.texture->currentnumlayers)
10128                         return;
10129                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10130                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10131                 else
10132                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10133         }
10134         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10135                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10136         else if (!rsurface.texture->currentnumlayers)
10137                 return;
10138         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10139         {
10140                 // in the deferred case, transparent surfaces were queued during prepass
10141                 if (!r_shadow_usingdeferredprepass)
10142                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10143         }
10144         else
10145         {
10146                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10147                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10148         }
10149         CHECKGLERROR
10150 }
10151
10152 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10153 {
10154         int i, j;
10155         texture_t *texture;
10156         R_FrameData_SetMark();
10157         // break the surface list down into batches by texture and use of lightmapping
10158         for (i = 0;i < numsurfaces;i = j)
10159         {
10160                 j = i + 1;
10161                 // texture is the base texture pointer, rsurface.texture is the
10162                 // current frame/skin the texture is directing us to use (for example
10163                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10164                 // use skin 1 instead)
10165                 texture = surfacelist[i]->texture;
10166                 rsurface.texture = R_GetCurrentTexture(texture);
10167                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10168                 {
10169                         // if this texture is not the kind we want, skip ahead to the next one
10170                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10171                                 ;
10172                         continue;
10173                 }
10174                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10175                 {
10176                         rsurface.lightmaptexture = NULL;
10177                         rsurface.deluxemaptexture = NULL;
10178                         rsurface.uselightmaptexture = false;
10179                         // simply scan ahead until we find a different texture or lightmap state
10180                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10181                                 ;
10182                 }
10183                 else
10184                 {
10185                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10186                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10187                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10188                         // simply scan ahead until we find a different texture or lightmap state
10189                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10190                                 ;
10191                 }
10192                 // render the range of surfaces
10193                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10194         }
10195         R_FrameData_ReturnToMark();
10196 }
10197
10198 float locboxvertex3f[6*4*3] =
10199 {
10200         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10201         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10202         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10203         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10204         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10205         1,0,0, 0,0,0, 0,1,0, 1,1,0
10206 };
10207
10208 unsigned short locboxelements[6*2*3] =
10209 {
10210          0, 1, 2, 0, 2, 3,
10211          4, 5, 6, 4, 6, 7,
10212          8, 9,10, 8,10,11,
10213         12,13,14, 12,14,15,
10214         16,17,18, 16,18,19,
10215         20,21,22, 20,22,23
10216 };
10217
10218 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10219 {
10220         int i, j;
10221         cl_locnode_t *loc = (cl_locnode_t *)ent;
10222         vec3_t mins, size;
10223         float vertex3f[6*4*3];
10224         CHECKGLERROR
10225         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10226         GL_DepthMask(false);
10227         GL_DepthRange(0, 1);
10228         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10229         GL_DepthTest(true);
10230         GL_CullFace(GL_NONE);
10231         R_EntityMatrix(&identitymatrix);
10232
10233 //      R_Mesh_ResetTextureState();
10234
10235         i = surfacelist[0];
10236         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10237                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10238                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10239                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10240
10241         if (VectorCompare(loc->mins, loc->maxs))
10242         {
10243                 VectorSet(size, 2, 2, 2);
10244                 VectorMA(loc->mins, -0.5f, size, mins);
10245         }
10246         else
10247         {
10248                 VectorCopy(loc->mins, mins);
10249                 VectorSubtract(loc->maxs, loc->mins, size);
10250         }
10251
10252         for (i = 0;i < 6*4*3;)
10253                 for (j = 0;j < 3;j++, i++)
10254                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10255
10256         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10257         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10258         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10259 }
10260
10261 void R_DrawLocs(void)
10262 {
10263         int index;
10264         cl_locnode_t *loc, *nearestloc;
10265         vec3_t center;
10266         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10267         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10268         {
10269                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10270                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10271         }
10272 }
10273
10274 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10275 {
10276         if (decalsystem->decals)
10277                 Mem_Free(decalsystem->decals);
10278         memset(decalsystem, 0, sizeof(*decalsystem));
10279 }
10280
10281 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)
10282 {
10283         tridecal_t *decal;
10284         tridecal_t *decals;
10285         int i;
10286
10287         // expand or initialize the system
10288         if (decalsystem->maxdecals <= decalsystem->numdecals)
10289         {
10290                 decalsystem_t old = *decalsystem;
10291                 qboolean useshortelements;
10292                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10293                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10294                 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)));
10295                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10296                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10297                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10298                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10299                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10300                 if (decalsystem->numdecals)
10301                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10302                 if (old.decals)
10303                         Mem_Free(old.decals);
10304                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10305                         decalsystem->element3i[i] = i;
10306                 if (useshortelements)
10307                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10308                                 decalsystem->element3s[i] = i;
10309         }
10310
10311         // grab a decal and search for another free slot for the next one
10312         decals = decalsystem->decals;
10313         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10314         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10315                 ;
10316         decalsystem->freedecal = i;
10317         if (decalsystem->numdecals <= i)
10318                 decalsystem->numdecals = i + 1;
10319
10320         // initialize the decal
10321         decal->lived = 0;
10322         decal->triangleindex = triangleindex;
10323         decal->surfaceindex = surfaceindex;
10324         decal->decalsequence = decalsequence;
10325         decal->color4f[0][0] = c0[0];
10326         decal->color4f[0][1] = c0[1];
10327         decal->color4f[0][2] = c0[2];
10328         decal->color4f[0][3] = 1;
10329         decal->color4f[1][0] = c1[0];
10330         decal->color4f[1][1] = c1[1];
10331         decal->color4f[1][2] = c1[2];
10332         decal->color4f[1][3] = 1;
10333         decal->color4f[2][0] = c2[0];
10334         decal->color4f[2][1] = c2[1];
10335         decal->color4f[2][2] = c2[2];
10336         decal->color4f[2][3] = 1;
10337         decal->vertex3f[0][0] = v0[0];
10338         decal->vertex3f[0][1] = v0[1];
10339         decal->vertex3f[0][2] = v0[2];
10340         decal->vertex3f[1][0] = v1[0];
10341         decal->vertex3f[1][1] = v1[1];
10342         decal->vertex3f[1][2] = v1[2];
10343         decal->vertex3f[2][0] = v2[0];
10344         decal->vertex3f[2][1] = v2[1];
10345         decal->vertex3f[2][2] = v2[2];
10346         decal->texcoord2f[0][0] = t0[0];
10347         decal->texcoord2f[0][1] = t0[1];
10348         decal->texcoord2f[1][0] = t1[0];
10349         decal->texcoord2f[1][1] = t1[1];
10350         decal->texcoord2f[2][0] = t2[0];
10351         decal->texcoord2f[2][1] = t2[1];
10352 }
10353
10354 extern cvar_t cl_decals_bias;
10355 extern cvar_t cl_decals_models;
10356 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10357 // baseparms, parms, temps
10358 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)
10359 {
10360         int cornerindex;
10361         int index;
10362         float v[9][3];
10363         const float *vertex3f;
10364         const float *normal3f;
10365         int numpoints;
10366         float points[2][9][3];
10367         float temp[3];
10368         float tc[9][2];
10369         float f;
10370         float c[9][4];
10371         const int *e;
10372
10373         e = rsurface.modelelement3i + 3*triangleindex;
10374
10375         vertex3f = rsurface.modelvertex3f;
10376         normal3f = rsurface.modelnormal3f;
10377
10378         if (normal3f)
10379         {
10380                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10381                 {
10382                         index = 3*e[cornerindex];
10383                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10384                 }
10385         }
10386         else
10387         {
10388                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10389                 {
10390                         index = 3*e[cornerindex];
10391                         VectorCopy(vertex3f + index, v[cornerindex]);
10392                 }
10393         }
10394
10395         // cull backfaces
10396         //TriangleNormal(v[0], v[1], v[2], normal);
10397         //if (DotProduct(normal, localnormal) < 0.0f)
10398         //      continue;
10399         // clip by each of the box planes formed from the projection matrix
10400         // if anything survives, we emit the decal
10401         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]);
10402         if (numpoints < 3)
10403                 return;
10404         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]);
10405         if (numpoints < 3)
10406                 return;
10407         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]);
10408         if (numpoints < 3)
10409                 return;
10410         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]);
10411         if (numpoints < 3)
10412                 return;
10413         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]);
10414         if (numpoints < 3)
10415                 return;
10416         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]);
10417         if (numpoints < 3)
10418                 return;
10419         // some part of the triangle survived, so we have to accept it...
10420         if (dynamic)
10421         {
10422                 // dynamic always uses the original triangle
10423                 numpoints = 3;
10424                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10425                 {
10426                         index = 3*e[cornerindex];
10427                         VectorCopy(vertex3f + index, v[cornerindex]);
10428                 }
10429         }
10430         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10431         {
10432                 // convert vertex positions to texcoords
10433                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10434                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10435                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10436                 // calculate distance fade from the projection origin
10437                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10438                 f = bound(0.0f, f, 1.0f);
10439                 c[cornerindex][0] = r * f;
10440                 c[cornerindex][1] = g * f;
10441                 c[cornerindex][2] = b * f;
10442                 c[cornerindex][3] = 1.0f;
10443                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10444         }
10445         if (dynamic)
10446                 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);
10447         else
10448                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10449                         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);
10450 }
10451 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)
10452 {
10453         matrix4x4_t projection;
10454         decalsystem_t *decalsystem;
10455         qboolean dynamic;
10456         dp_model_t *model;
10457         const msurface_t *surface;
10458         const msurface_t *surfaces;
10459         const int *surfacelist;
10460         const texture_t *texture;
10461         int numtriangles;
10462         int numsurfacelist;
10463         int surfacelistindex;
10464         int surfaceindex;
10465         int triangleindex;
10466         float localorigin[3];
10467         float localnormal[3];
10468         float localmins[3];
10469         float localmaxs[3];
10470         float localsize;
10471         //float normal[3];
10472         float planes[6][4];
10473         float angles[3];
10474         bih_t *bih;
10475         int bih_triangles_count;
10476         int bih_triangles[256];
10477         int bih_surfaces[256];
10478
10479         decalsystem = &ent->decalsystem;
10480         model = ent->model;
10481         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10482         {
10483                 R_DecalSystem_Reset(&ent->decalsystem);
10484                 return;
10485         }
10486
10487         if (!model->brush.data_leafs && !cl_decals_models.integer)
10488         {
10489                 if (decalsystem->model)
10490                         R_DecalSystem_Reset(decalsystem);
10491                 return;
10492         }
10493
10494         if (decalsystem->model != model)
10495                 R_DecalSystem_Reset(decalsystem);
10496         decalsystem->model = model;
10497
10498         RSurf_ActiveModelEntity(ent, true, false, false);
10499
10500         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10501         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10502         VectorNormalize(localnormal);
10503         localsize = worldsize*rsurface.inversematrixscale;
10504         localmins[0] = localorigin[0] - localsize;
10505         localmins[1] = localorigin[1] - localsize;
10506         localmins[2] = localorigin[2] - localsize;
10507         localmaxs[0] = localorigin[0] + localsize;
10508         localmaxs[1] = localorigin[1] + localsize;
10509         localmaxs[2] = localorigin[2] + localsize;
10510
10511         //VectorCopy(localnormal, planes[4]);
10512         //VectorVectors(planes[4], planes[2], planes[0]);
10513         AnglesFromVectors(angles, localnormal, NULL, false);
10514         AngleVectors(angles, planes[0], planes[2], planes[4]);
10515         VectorNegate(planes[0], planes[1]);
10516         VectorNegate(planes[2], planes[3]);
10517         VectorNegate(planes[4], planes[5]);
10518         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10519         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10520         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10521         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10522         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10523         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10524
10525 #if 1
10526 // works
10527 {
10528         matrix4x4_t forwardprojection;
10529         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10530         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10531 }
10532 #else
10533 // broken
10534 {
10535         float projectionvector[4][3];
10536         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10537         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10538         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10539         projectionvector[0][0] = planes[0][0] * ilocalsize;
10540         projectionvector[0][1] = planes[1][0] * ilocalsize;
10541         projectionvector[0][2] = planes[2][0] * ilocalsize;
10542         projectionvector[1][0] = planes[0][1] * ilocalsize;
10543         projectionvector[1][1] = planes[1][1] * ilocalsize;
10544         projectionvector[1][2] = planes[2][1] * ilocalsize;
10545         projectionvector[2][0] = planes[0][2] * ilocalsize;
10546         projectionvector[2][1] = planes[1][2] * ilocalsize;
10547         projectionvector[2][2] = planes[2][2] * ilocalsize;
10548         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10549         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10550         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10551         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10552 }
10553 #endif
10554
10555         dynamic = model->surfmesh.isanimated;
10556         numsurfacelist = model->nummodelsurfaces;
10557         surfacelist = model->sortedmodelsurfaces;
10558         surfaces = model->data_surfaces;
10559
10560         bih = NULL;
10561         bih_triangles_count = -1;
10562         if(!dynamic)
10563         {
10564                 if(model->render_bih.numleafs)
10565                         bih = &model->render_bih;
10566                 else if(model->collision_bih.numleafs)
10567                         bih = &model->collision_bih;
10568         }
10569         if(bih)
10570                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10571         if(bih_triangles_count == 0)
10572                 return;
10573         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10574                 return;
10575         if(bih_triangles_count > 0)
10576         {
10577                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10578                 {
10579                         surfaceindex = bih_surfaces[triangleindex];
10580                         surface = surfaces + surfaceindex;
10581                         texture = surface->texture;
10582                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10583                                 continue;
10584                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10585                                 continue;
10586                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10587                 }
10588         }
10589         else
10590         {
10591                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10592                 {
10593                         surfaceindex = surfacelist[surfacelistindex];
10594                         surface = surfaces + surfaceindex;
10595                         // check cull box first because it rejects more than any other check
10596                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10597                                 continue;
10598                         // skip transparent surfaces
10599                         texture = surface->texture;
10600                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10601                                 continue;
10602                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10603                                 continue;
10604                         numtriangles = surface->num_triangles;
10605                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10606                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10607                 }
10608         }
10609 }
10610
10611 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10612 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)
10613 {
10614         int renderentityindex;
10615         float worldmins[3];
10616         float worldmaxs[3];
10617         entity_render_t *ent;
10618
10619         if (!cl_decals_newsystem.integer)
10620                 return;
10621
10622         worldmins[0] = worldorigin[0] - worldsize;
10623         worldmins[1] = worldorigin[1] - worldsize;
10624         worldmins[2] = worldorigin[2] - worldsize;
10625         worldmaxs[0] = worldorigin[0] + worldsize;
10626         worldmaxs[1] = worldorigin[1] + worldsize;
10627         worldmaxs[2] = worldorigin[2] + worldsize;
10628
10629         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10630
10631         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10632         {
10633                 ent = r_refdef.scene.entities[renderentityindex];
10634                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10635                         continue;
10636
10637                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10638         }
10639 }
10640
10641 typedef struct r_decalsystem_splatqueue_s
10642 {
10643         vec3_t worldorigin;
10644         vec3_t worldnormal;
10645         float color[4];
10646         float tcrange[4];
10647         float worldsize;
10648         int decalsequence;
10649 }
10650 r_decalsystem_splatqueue_t;
10651
10652 int r_decalsystem_numqueued = 0;
10653 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10654
10655 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)
10656 {
10657         r_decalsystem_splatqueue_t *queue;
10658
10659         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10660                 return;
10661
10662         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10663         VectorCopy(worldorigin, queue->worldorigin);
10664         VectorCopy(worldnormal, queue->worldnormal);
10665         Vector4Set(queue->color, r, g, b, a);
10666         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10667         queue->worldsize = worldsize;
10668         queue->decalsequence = cl.decalsequence++;
10669 }
10670
10671 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10672 {
10673         int i;
10674         r_decalsystem_splatqueue_t *queue;
10675
10676         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10677                 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);
10678         r_decalsystem_numqueued = 0;
10679 }
10680
10681 extern cvar_t cl_decals_max;
10682 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10683 {
10684         int i;
10685         decalsystem_t *decalsystem = &ent->decalsystem;
10686         int numdecals;
10687         int killsequence;
10688         tridecal_t *decal;
10689         float frametime;
10690         float lifetime;
10691
10692         if (!decalsystem->numdecals)
10693                 return;
10694
10695         if (r_showsurfaces.integer)
10696                 return;
10697
10698         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10699         {
10700                 R_DecalSystem_Reset(decalsystem);
10701                 return;
10702         }
10703
10704         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10705         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10706
10707         if (decalsystem->lastupdatetime)
10708                 frametime = (cl.time - decalsystem->lastupdatetime);
10709         else
10710                 frametime = 0;
10711         decalsystem->lastupdatetime = cl.time;
10712         decal = decalsystem->decals;
10713         numdecals = decalsystem->numdecals;
10714
10715         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10716         {
10717                 if (decal->color4f[0][3])
10718                 {
10719                         decal->lived += frametime;
10720                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10721                         {
10722                                 memset(decal, 0, sizeof(*decal));
10723                                 if (decalsystem->freedecal > i)
10724                                         decalsystem->freedecal = i;
10725                         }
10726                 }
10727         }
10728         decal = decalsystem->decals;
10729         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10730                 numdecals--;
10731
10732         // collapse the array by shuffling the tail decals into the gaps
10733         for (;;)
10734         {
10735                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10736                         decalsystem->freedecal++;
10737                 if (decalsystem->freedecal == numdecals)
10738                         break;
10739                 decal[decalsystem->freedecal] = decal[--numdecals];
10740         }
10741
10742         decalsystem->numdecals = numdecals;
10743
10744         if (numdecals <= 0)
10745         {
10746                 // if there are no decals left, reset decalsystem
10747                 R_DecalSystem_Reset(decalsystem);
10748         }
10749 }
10750
10751 extern skinframe_t *decalskinframe;
10752 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10753 {
10754         int i;
10755         decalsystem_t *decalsystem = &ent->decalsystem;
10756         int numdecals;
10757         tridecal_t *decal;
10758         float faderate;
10759         float alpha;
10760         float *v3f;
10761         float *c4f;
10762         float *t2f;
10763         const int *e;
10764         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10765         int numtris = 0;
10766
10767         numdecals = decalsystem->numdecals;
10768         if (!numdecals)
10769                 return;
10770
10771         if (r_showsurfaces.integer)
10772                 return;
10773
10774         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10775         {
10776                 R_DecalSystem_Reset(decalsystem);
10777                 return;
10778         }
10779
10780         // if the model is static it doesn't matter what value we give for
10781         // wantnormals and wanttangents, so this logic uses only rules applicable
10782         // to a model, knowing that they are meaningless otherwise
10783         if (ent == r_refdef.scene.worldentity)
10784                 RSurf_ActiveWorldEntity();
10785         else
10786                 RSurf_ActiveModelEntity(ent, false, false, false);
10787
10788         decalsystem->lastupdatetime = cl.time;
10789         decal = decalsystem->decals;
10790
10791         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10792
10793         // update vertex positions for animated models
10794         v3f = decalsystem->vertex3f;
10795         c4f = decalsystem->color4f;
10796         t2f = decalsystem->texcoord2f;
10797         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10798         {
10799                 if (!decal->color4f[0][3])
10800                         continue;
10801
10802                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10803                         continue;
10804
10805                 // update color values for fading decals
10806                 if (decal->lived >= cl_decals_time.value)
10807                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10808                 else
10809                         alpha = 1.0f;
10810
10811                 c4f[ 0] = decal->color4f[0][0] * alpha;
10812                 c4f[ 1] = decal->color4f[0][1] * alpha;
10813                 c4f[ 2] = decal->color4f[0][2] * alpha;
10814                 c4f[ 3] = 1;
10815                 c4f[ 4] = decal->color4f[1][0] * alpha;
10816                 c4f[ 5] = decal->color4f[1][1] * alpha;
10817                 c4f[ 6] = decal->color4f[1][2] * alpha;
10818                 c4f[ 7] = 1;
10819                 c4f[ 8] = decal->color4f[2][0] * alpha;
10820                 c4f[ 9] = decal->color4f[2][1] * alpha;
10821                 c4f[10] = decal->color4f[2][2] * alpha;
10822                 c4f[11] = 1;
10823
10824                 t2f[0] = decal->texcoord2f[0][0];
10825                 t2f[1] = decal->texcoord2f[0][1];
10826                 t2f[2] = decal->texcoord2f[1][0];
10827                 t2f[3] = decal->texcoord2f[1][1];
10828                 t2f[4] = decal->texcoord2f[2][0];
10829                 t2f[5] = decal->texcoord2f[2][1];
10830
10831                 // update vertex positions for animated models
10832                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10833                 {
10834                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10835                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10836                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10837                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10838                 }
10839                 else
10840                 {
10841                         VectorCopy(decal->vertex3f[0], v3f);
10842                         VectorCopy(decal->vertex3f[1], v3f + 3);
10843                         VectorCopy(decal->vertex3f[2], v3f + 6);
10844                 }
10845
10846                 if (r_refdef.fogenabled)
10847                 {
10848                         alpha = RSurf_FogVertex(v3f);
10849                         VectorScale(c4f, alpha, c4f);
10850                         alpha = RSurf_FogVertex(v3f + 3);
10851                         VectorScale(c4f + 4, alpha, c4f + 4);
10852                         alpha = RSurf_FogVertex(v3f + 6);
10853                         VectorScale(c4f + 8, alpha, c4f + 8);
10854                 }
10855
10856                 v3f += 9;
10857                 c4f += 12;
10858                 t2f += 6;
10859                 numtris++;
10860         }
10861
10862         if (numtris > 0)
10863         {
10864                 r_refdef.stats.drawndecals += numtris;
10865
10866                 // now render the decals all at once
10867                 // (this assumes they all use one particle font texture!)
10868                 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);
10869 //              R_Mesh_ResetTextureState();
10870                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10871                 GL_DepthMask(false);
10872                 GL_DepthRange(0, 1);
10873                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10874                 GL_DepthTest(true);
10875                 GL_CullFace(GL_NONE);
10876                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10877                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10878                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10879         }
10880 }
10881
10882 static void R_DrawModelDecals(void)
10883 {
10884         int i, numdecals;
10885
10886         // fade faster when there are too many decals
10887         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10888         for (i = 0;i < r_refdef.scene.numentities;i++)
10889                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10890
10891         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10892         for (i = 0;i < r_refdef.scene.numentities;i++)
10893                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10894                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10895
10896         R_DecalSystem_ApplySplatEntitiesQueue();
10897
10898         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10899         for (i = 0;i < r_refdef.scene.numentities;i++)
10900                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10901
10902         r_refdef.stats.totaldecals += numdecals;
10903
10904         if (r_showsurfaces.integer)
10905                 return;
10906
10907         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10908
10909         for (i = 0;i < r_refdef.scene.numentities;i++)
10910         {
10911                 if (!r_refdef.viewcache.entityvisible[i])
10912                         continue;
10913                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10914                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10915         }
10916 }
10917
10918 extern cvar_t mod_collision_bih;
10919 void R_DrawDebugModel(void)
10920 {
10921         entity_render_t *ent = rsurface.entity;
10922         int i, j, k, l, flagsmask;
10923         const msurface_t *surface;
10924         dp_model_t *model = ent->model;
10925         vec3_t v;
10926
10927         switch(vid.renderpath)
10928         {
10929         case RENDERPATH_GL11:
10930         case RENDERPATH_GL13:
10931         case RENDERPATH_GL20:
10932                 break;
10933         case RENDERPATH_D3D9:
10934                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10935                 return;
10936         case RENDERPATH_D3D10:
10937                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10938                 return;
10939         case RENDERPATH_D3D11:
10940                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10941                 return;
10942         case RENDERPATH_SOFT:
10943                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10944                 return;
10945         case RENDERPATH_GLES2:
10946                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10947                 return;
10948         }
10949
10950         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10951
10952 //      R_Mesh_ResetTextureState();
10953         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10954         GL_DepthRange(0, 1);
10955         GL_DepthTest(!r_showdisabledepthtest.integer);
10956         GL_DepthMask(false);
10957         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10958
10959         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10960         {
10961                 int triangleindex;
10962                 int bihleafindex;
10963                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10964                 const q3mbrush_t *brush;
10965                 const bih_t *bih = &model->collision_bih;
10966                 const bih_leaf_t *bihleaf;
10967                 float vertex3f[3][3];
10968                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10969                 cullbox = false;
10970                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10971                 {
10972                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10973                                 continue;
10974                         switch (bihleaf->type)
10975                         {
10976                         case BIH_BRUSH:
10977                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10978                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10979                                 {
10980                                         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);
10981                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10982                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10983                                 }
10984                                 break;
10985                         case BIH_COLLISIONTRIANGLE:
10986                                 triangleindex = bihleaf->itemindex;
10987                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10988                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10989                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10990                                 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);
10991                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10992                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10993                                 break;
10994                         case BIH_RENDERTRIANGLE:
10995                                 triangleindex = bihleaf->itemindex;
10996                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10997                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10998                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10999                                 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);
11000                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11001                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11002                                 break;
11003                         }
11004                 }
11005         }
11006
11007         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11008
11009         if (r_showtris.integer || (r_shownormals.value != 0))
11010         {
11011                 if (r_showdisabledepthtest.integer)
11012                 {
11013                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11014                         GL_DepthMask(false);
11015                 }
11016                 else
11017                 {
11018                         GL_BlendFunc(GL_ONE, GL_ZERO);
11019                         GL_DepthMask(true);
11020                 }
11021                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11022                 {
11023                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11024                                 continue;
11025                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11026                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11027                         {
11028                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11029                                 if (r_showtris.value > 0)
11030                                 {
11031                                         if (!rsurface.texture->currentlayers->depthmask)
11032                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11033                                         else if (ent == r_refdef.scene.worldentity)
11034                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11035                                         else
11036                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11037                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11038                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11039                                         RSurf_DrawBatch();
11040                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11041                                         CHECKGLERROR
11042                                 }
11043                                 if (r_shownormals.value < 0)
11044                                 {
11045                                         qglBegin(GL_LINES);
11046                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11047                                         {
11048                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11049                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11050                                                 qglVertex3f(v[0], v[1], v[2]);
11051                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11052                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11053                                                 qglVertex3f(v[0], v[1], v[2]);
11054                                         }
11055                                         qglEnd();
11056                                         CHECKGLERROR
11057                                 }
11058                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11059                                 {
11060                                         qglBegin(GL_LINES);
11061                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11062                                         {
11063                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11064                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11065                                                 qglVertex3f(v[0], v[1], v[2]);
11066                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11067                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11068                                                 qglVertex3f(v[0], v[1], v[2]);
11069                                         }
11070                                         qglEnd();
11071                                         CHECKGLERROR
11072                                         qglBegin(GL_LINES);
11073                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11074                                         {
11075                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11076                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11077                                                 qglVertex3f(v[0], v[1], v[2]);
11078                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11079                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11080                                                 qglVertex3f(v[0], v[1], v[2]);
11081                                         }
11082                                         qglEnd();
11083                                         CHECKGLERROR
11084                                         qglBegin(GL_LINES);
11085                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11086                                         {
11087                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11088                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11089                                                 qglVertex3f(v[0], v[1], v[2]);
11090                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11091                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11092                                                 qglVertex3f(v[0], v[1], v[2]);
11093                                         }
11094                                         qglEnd();
11095                                         CHECKGLERROR
11096                                 }
11097                         }
11098                 }
11099                 rsurface.texture = NULL;
11100         }
11101 }
11102
11103 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11104 int r_maxsurfacelist = 0;
11105 const msurface_t **r_surfacelist = NULL;
11106 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11107 {
11108         int i, j, endj, flagsmask;
11109         dp_model_t *model = r_refdef.scene.worldmodel;
11110         msurface_t *surfaces;
11111         unsigned char *update;
11112         int numsurfacelist = 0;
11113         if (model == NULL)
11114                 return;
11115
11116         if (r_maxsurfacelist < model->num_surfaces)
11117         {
11118                 r_maxsurfacelist = model->num_surfaces;
11119                 if (r_surfacelist)
11120                         Mem_Free((msurface_t**)r_surfacelist);
11121                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11122         }
11123
11124         RSurf_ActiveWorldEntity();
11125
11126         surfaces = model->data_surfaces;
11127         update = model->brushq1.lightmapupdateflags;
11128
11129         // update light styles on this submodel
11130         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11131         {
11132                 model_brush_lightstyleinfo_t *style;
11133                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11134                 {
11135                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11136                         {
11137                                 int *list = style->surfacelist;
11138                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11139                                 for (j = 0;j < style->numsurfaces;j++)
11140                                         update[list[j]] = true;
11141                         }
11142                 }
11143         }
11144
11145         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11146
11147         if (debug)
11148         {
11149                 R_DrawDebugModel();
11150                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11151                 return;
11152         }
11153
11154         rsurface.lightmaptexture = NULL;
11155         rsurface.deluxemaptexture = NULL;
11156         rsurface.uselightmaptexture = false;
11157         rsurface.texture = NULL;
11158         rsurface.rtlight = NULL;
11159         numsurfacelist = 0;
11160         // add visible surfaces to draw list
11161         for (i = 0;i < model->nummodelsurfaces;i++)
11162         {
11163                 j = model->sortedmodelsurfaces[i];
11164                 if (r_refdef.viewcache.world_surfacevisible[j])
11165                         r_surfacelist[numsurfacelist++] = surfaces + j;
11166         }
11167         // update lightmaps if needed
11168         if (model->brushq1.firstrender)
11169         {
11170                 model->brushq1.firstrender = false;
11171                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11172                         if (update[j])
11173                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11174         }
11175         else if (update)
11176         {
11177                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11178                         if (r_refdef.viewcache.world_surfacevisible[j])
11179                                 if (update[j])
11180                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11181         }
11182         // don't do anything if there were no surfaces
11183         if (!numsurfacelist)
11184         {
11185                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11186                 return;
11187         }
11188         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11189
11190         // add to stats if desired
11191         if (r_speeds.integer && !skysurfaces && !depthonly)
11192         {
11193                 r_refdef.stats.world_surfaces += numsurfacelist;
11194                 for (j = 0;j < numsurfacelist;j++)
11195                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11196         }
11197
11198         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11199 }
11200
11201 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11202 {
11203         int i, j, endj, flagsmask;
11204         dp_model_t *model = ent->model;
11205         msurface_t *surfaces;
11206         unsigned char *update;
11207         int numsurfacelist = 0;
11208         if (model == NULL)
11209                 return;
11210
11211         if (r_maxsurfacelist < model->num_surfaces)
11212         {
11213                 r_maxsurfacelist = model->num_surfaces;
11214                 if (r_surfacelist)
11215                         Mem_Free((msurface_t **)r_surfacelist);
11216                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11217         }
11218
11219         // if the model is static it doesn't matter what value we give for
11220         // wantnormals and wanttangents, so this logic uses only rules applicable
11221         // to a model, knowing that they are meaningless otherwise
11222         if (ent == r_refdef.scene.worldentity)
11223                 RSurf_ActiveWorldEntity();
11224         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11225                 RSurf_ActiveModelEntity(ent, false, false, false);
11226         else if (prepass)
11227                 RSurf_ActiveModelEntity(ent, true, true, true);
11228         else if (depthonly)
11229         {
11230                 switch (vid.renderpath)
11231                 {
11232                 case RENDERPATH_GL20:
11233                 case RENDERPATH_D3D9:
11234                 case RENDERPATH_D3D10:
11235                 case RENDERPATH_D3D11:
11236                 case RENDERPATH_SOFT:
11237                 case RENDERPATH_GLES2:
11238                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11239                         break;
11240                 case RENDERPATH_GL13:
11241                 case RENDERPATH_GL11:
11242                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11243                         break;
11244                 }
11245         }
11246         else
11247         {
11248                 switch (vid.renderpath)
11249                 {
11250                 case RENDERPATH_GL20:
11251                 case RENDERPATH_D3D9:
11252                 case RENDERPATH_D3D10:
11253                 case RENDERPATH_D3D11:
11254                 case RENDERPATH_SOFT:
11255                 case RENDERPATH_GLES2:
11256                         RSurf_ActiveModelEntity(ent, true, true, false);
11257                         break;
11258                 case RENDERPATH_GL13:
11259                 case RENDERPATH_GL11:
11260                         RSurf_ActiveModelEntity(ent, true, false, false);
11261                         break;
11262                 }
11263         }
11264
11265         surfaces = model->data_surfaces;
11266         update = model->brushq1.lightmapupdateflags;
11267
11268         // update light styles
11269         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11270         {
11271                 model_brush_lightstyleinfo_t *style;
11272                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11273                 {
11274                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11275                         {
11276                                 int *list = style->surfacelist;
11277                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11278                                 for (j = 0;j < style->numsurfaces;j++)
11279                                         update[list[j]] = true;
11280                         }
11281                 }
11282         }
11283
11284         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11285
11286         if (debug)
11287         {
11288                 R_DrawDebugModel();
11289                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11290                 return;
11291         }
11292
11293         rsurface.lightmaptexture = NULL;
11294         rsurface.deluxemaptexture = NULL;
11295         rsurface.uselightmaptexture = false;
11296         rsurface.texture = NULL;
11297         rsurface.rtlight = NULL;
11298         numsurfacelist = 0;
11299         // add visible surfaces to draw list
11300         for (i = 0;i < model->nummodelsurfaces;i++)
11301                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11302         // don't do anything if there were no surfaces
11303         if (!numsurfacelist)
11304         {
11305                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11306                 return;
11307         }
11308         // update lightmaps if needed
11309         if (update)
11310         {
11311                 int updated = 0;
11312                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11313                 {
11314                         if (update[j])
11315                         {
11316                                 updated++;
11317                                 R_BuildLightMap(ent, surfaces + j);
11318                         }
11319                 }
11320         }
11321         if (update)
11322                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11323                         if (update[j])
11324                                 R_BuildLightMap(ent, surfaces + j);
11325         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11326
11327         // add to stats if desired
11328         if (r_speeds.integer && !skysurfaces && !depthonly)
11329         {
11330                 r_refdef.stats.entities_surfaces += numsurfacelist;
11331                 for (j = 0;j < numsurfacelist;j++)
11332                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11333         }
11334
11335         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11336 }
11337
11338 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11339 {
11340         static texture_t texture;
11341         static msurface_t surface;
11342         const msurface_t *surfacelist = &surface;
11343
11344         // fake enough texture and surface state to render this geometry
11345
11346         texture.update_lastrenderframe = -1; // regenerate this texture
11347         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11348         texture.currentskinframe = skinframe;
11349         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11350         texture.offsetmapping = OFFSETMAPPING_OFF;
11351         texture.offsetscale = 1;
11352         texture.specularscalemod = 1;
11353         texture.specularpowermod = 1;
11354
11355         surface.texture = &texture;
11356         surface.num_triangles = numtriangles;
11357         surface.num_firsttriangle = firsttriangle;
11358         surface.num_vertices = numvertices;
11359         surface.num_firstvertex = firstvertex;
11360
11361         // now render it
11362         rsurface.texture = R_GetCurrentTexture(surface.texture);
11363         rsurface.lightmaptexture = NULL;
11364         rsurface.deluxemaptexture = NULL;
11365         rsurface.uselightmaptexture = false;
11366         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11367 }
11368
11369 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)
11370 {
11371         static msurface_t surface;
11372         const msurface_t *surfacelist = &surface;
11373
11374         // fake enough texture and surface state to render this geometry
11375         surface.texture = texture;
11376         surface.num_triangles = numtriangles;
11377         surface.num_firsttriangle = firsttriangle;
11378         surface.num_vertices = numvertices;
11379         surface.num_firstvertex = firstvertex;
11380
11381         // now render it
11382         rsurface.texture = R_GetCurrentTexture(surface.texture);
11383         rsurface.lightmaptexture = NULL;
11384         rsurface.deluxemaptexture = NULL;
11385         rsurface.uselightmaptexture = false;
11386         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11387 }