]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix an array index out of bounds error on
[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_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 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"};
120
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129
130 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)"};
131 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"};
132
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142
143 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)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 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)"};
146 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
147 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)"};
148 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
149 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
150 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)"};
151 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)"};
152 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)"};
153 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)"};
154 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)"};
155 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)"};
156 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)"};
157 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)"};
158
159 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)"};
160 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
161 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"};
162 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
163 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
164 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
165
166 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
167 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
168 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
169 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
170
171 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
172 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
173 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
174 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
175 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
176 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
177 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
178
179 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
180 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
181 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
182 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)"};
183 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
184 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
185 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
186 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
187 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
188 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
189
190 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"};
191
192 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"};
193
194 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
195
196 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
197 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"};
198 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
199 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
200 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
201 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
202 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)"};
203 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
204 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
205
206 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
207 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"};
208
209 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."};
210
211 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)"};
212
213 extern cvar_t v_glslgamma;
214
215 extern qboolean v_flipped_state;
216
217 static struct r_bloomstate_s
218 {
219         qboolean enabled;
220         qboolean hdr;
221
222         int bloomwidth, bloomheight;
223
224         int screentexturewidth, screentextureheight;
225         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
226
227         int bloomtexturewidth, bloomtextureheight;
228         rtexture_t *texture_bloom;
229
230         // arrays for rendering the screen passes
231         float screentexcoord2f[8];
232         float bloomtexcoord2f[8];
233         float offsettexcoord2f[8];
234
235         r_viewport_t viewport;
236 }
237 r_bloomstate;
238
239 r_waterstate_t r_waterstate;
240
241 /// shadow volume bsp struct with automatically growing nodes buffer
242 svbsp_t r_svbsp;
243
244 rtexture_t *r_texture_blanknormalmap;
245 rtexture_t *r_texture_white;
246 rtexture_t *r_texture_grey128;
247 rtexture_t *r_texture_black;
248 rtexture_t *r_texture_notexture;
249 rtexture_t *r_texture_whitecube;
250 rtexture_t *r_texture_normalizationcube;
251 rtexture_t *r_texture_fogattenuation;
252 rtexture_t *r_texture_fogheighttexture;
253 rtexture_t *r_texture_gammaramps;
254 unsigned int r_texture_gammaramps_serial;
255 //rtexture_t *r_texture_fogintensity;
256 rtexture_t *r_texture_reflectcube;
257
258 // TODO: hash lookups?
259 typedef struct cubemapinfo_s
260 {
261         char basename[64];
262         rtexture_t *texture;
263 }
264 cubemapinfo_t;
265
266 int r_texture_numcubemaps;
267 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
268
269 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
270 unsigned int r_numqueries;
271 unsigned int r_maxqueries;
272
273 typedef struct r_qwskincache_s
274 {
275         char name[MAX_QPATH];
276         skinframe_t *skinframe;
277 }
278 r_qwskincache_t;
279
280 static r_qwskincache_t *r_qwskincache;
281 static int r_qwskincache_size;
282
283 /// vertex coordinates for a quad that covers the screen exactly
284 extern const float r_screenvertex3f[12];
285 extern const float r_d3dscreenvertex3f[12];
286 const float r_screenvertex3f[12] =
287 {
288         0, 0, 0,
289         1, 0, 0,
290         1, 1, 0,
291         0, 1, 0
292 };
293 const float r_d3dscreenvertex3f[12] =
294 {
295         0, 1, 0,
296         1, 1, 0,
297         1, 0, 0,
298         0, 0, 0
299 };
300
301 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
302 {
303         int i;
304         for (i = 0;i < verts;i++)
305         {
306                 out[0] = in[0] * r;
307                 out[1] = in[1] * g;
308                 out[2] = in[2] * b;
309                 out[3] = in[3];
310                 in += 4;
311                 out += 4;
312         }
313 }
314
315 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
316 {
317         int i;
318         for (i = 0;i < verts;i++)
319         {
320                 out[0] = r;
321                 out[1] = g;
322                 out[2] = b;
323                 out[3] = a;
324                 out += 4;
325         }
326 }
327
328 // FIXME: move this to client?
329 void FOG_clear(void)
330 {
331         if (gamemode == GAME_NEHAHRA)
332         {
333                 Cvar_Set("gl_fogenable", "0");
334                 Cvar_Set("gl_fogdensity", "0.2");
335                 Cvar_Set("gl_fogred", "0.3");
336                 Cvar_Set("gl_foggreen", "0.3");
337                 Cvar_Set("gl_fogblue", "0.3");
338         }
339         r_refdef.fog_density = 0;
340         r_refdef.fog_red = 0;
341         r_refdef.fog_green = 0;
342         r_refdef.fog_blue = 0;
343         r_refdef.fog_alpha = 1;
344         r_refdef.fog_start = 0;
345         r_refdef.fog_end = 16384;
346         r_refdef.fog_height = 1<<30;
347         r_refdef.fog_fadedepth = 128;
348         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
349 }
350
351 static void R_BuildBlankTextures(void)
352 {
353         unsigned char data[4];
354         data[2] = 128; // normal X
355         data[1] = 128; // normal Y
356         data[0] = 255; // normal Z
357         data[3] = 128; // height
358         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359         data[0] = 255;
360         data[1] = 255;
361         data[2] = 255;
362         data[3] = 255;
363         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364         data[0] = 128;
365         data[1] = 128;
366         data[2] = 128;
367         data[3] = 255;
368         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369         data[0] = 0;
370         data[1] = 0;
371         data[2] = 0;
372         data[3] = 255;
373         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 }
375
376 static void R_BuildNoTexture(void)
377 {
378         int x, y;
379         unsigned char pix[16][16][4];
380         // this makes a light grey/dark grey checkerboard texture
381         for (y = 0;y < 16;y++)
382         {
383                 for (x = 0;x < 16;x++)
384                 {
385                         if ((y < 8) ^ (x < 8))
386                         {
387                                 pix[y][x][0] = 128;
388                                 pix[y][x][1] = 128;
389                                 pix[y][x][2] = 128;
390                                 pix[y][x][3] = 255;
391                         }
392                         else
393                         {
394                                 pix[y][x][0] = 64;
395                                 pix[y][x][1] = 64;
396                                 pix[y][x][2] = 64;
397                                 pix[y][x][3] = 255;
398                         }
399                 }
400         }
401         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
402 }
403
404 static void R_BuildWhiteCube(void)
405 {
406         unsigned char data[6*1*1*4];
407         memset(data, 255, sizeof(data));
408         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
409 }
410
411 static void R_BuildNormalizationCube(void)
412 {
413         int x, y, side;
414         vec3_t v;
415         vec_t s, t, intensity;
416 #define NORMSIZE 64
417         unsigned char *data;
418         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
419         for (side = 0;side < 6;side++)
420         {
421                 for (y = 0;y < NORMSIZE;y++)
422                 {
423                         for (x = 0;x < NORMSIZE;x++)
424                         {
425                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
426                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
427                                 switch(side)
428                                 {
429                                 default:
430                                 case 0:
431                                         v[0] = 1;
432                                         v[1] = -t;
433                                         v[2] = -s;
434                                         break;
435                                 case 1:
436                                         v[0] = -1;
437                                         v[1] = -t;
438                                         v[2] = s;
439                                         break;
440                                 case 2:
441                                         v[0] = s;
442                                         v[1] = 1;
443                                         v[2] = t;
444                                         break;
445                                 case 3:
446                                         v[0] = s;
447                                         v[1] = -1;
448                                         v[2] = -t;
449                                         break;
450                                 case 4:
451                                         v[0] = s;
452                                         v[1] = -t;
453                                         v[2] = 1;
454                                         break;
455                                 case 5:
456                                         v[0] = -s;
457                                         v[1] = -t;
458                                         v[2] = -1;
459                                         break;
460                                 }
461                                 intensity = 127.0f / sqrt(DotProduct(v, v));
462                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
463                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
464                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
465                                 data[((side*64+y)*64+x)*4+3] = 255;
466                         }
467                 }
468         }
469         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
470         Mem_Free(data);
471 }
472
473 static void R_BuildFogTexture(void)
474 {
475         int x, b;
476 #define FOGWIDTH 256
477         unsigned char data1[FOGWIDTH][4];
478         //unsigned char data2[FOGWIDTH][4];
479         double d, r, alpha;
480
481         r_refdef.fogmasktable_start = r_refdef.fog_start;
482         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
483         r_refdef.fogmasktable_range = r_refdef.fogrange;
484         r_refdef.fogmasktable_density = r_refdef.fog_density;
485
486         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
487         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
488         {
489                 d = (x * r - r_refdef.fogmasktable_start);
490                 if(developer_extra.integer)
491                         Con_DPrintf("%f ", d);
492                 d = max(0, d);
493                 if (r_fog_exp2.integer)
494                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
495                 else
496                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
497                 if(developer_extra.integer)
498                         Con_DPrintf(" : %f ", alpha);
499                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
500                 if(developer_extra.integer)
501                         Con_DPrintf(" = %f\n", alpha);
502                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
503         }
504
505         for (x = 0;x < FOGWIDTH;x++)
506         {
507                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
508                 data1[x][0] = b;
509                 data1[x][1] = b;
510                 data1[x][2] = b;
511                 data1[x][3] = 255;
512                 //data2[x][0] = 255 - b;
513                 //data2[x][1] = 255 - b;
514                 //data2[x][2] = 255 - b;
515                 //data2[x][3] = 255;
516         }
517         if (r_texture_fogattenuation)
518         {
519                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
520                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
521         }
522         else
523         {
524                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
525                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
526         }
527 }
528
529 static void R_BuildFogHeightTexture(void)
530 {
531         unsigned char *inpixels;
532         int size;
533         int x;
534         int y;
535         int j;
536         float c[4];
537         float f;
538         inpixels = NULL;
539         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
540         if (r_refdef.fogheighttexturename[0])
541                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
542         if (!inpixels)
543         {
544                 r_refdef.fog_height_tablesize = 0;
545                 if (r_texture_fogheighttexture)
546                         R_FreeTexture(r_texture_fogheighttexture);
547                 r_texture_fogheighttexture = NULL;
548                 if (r_refdef.fog_height_table2d)
549                         Mem_Free(r_refdef.fog_height_table2d);
550                 r_refdef.fog_height_table2d = NULL;
551                 if (r_refdef.fog_height_table1d)
552                         Mem_Free(r_refdef.fog_height_table1d);
553                 r_refdef.fog_height_table1d = NULL;
554                 return;
555         }
556         size = image_width;
557         r_refdef.fog_height_tablesize = size;
558         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
559         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
560         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
561         Mem_Free(inpixels);
562         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
563         // average fog color table accounting for every fog layer between a point
564         // and the camera.  (Note: attenuation is handled separately!)
565         for (y = 0;y < size;y++)
566         {
567                 for (x = 0;x < size;x++)
568                 {
569                         Vector4Clear(c);
570                         f = 0;
571                         if (x < y)
572                         {
573                                 for (j = x;j <= y;j++)
574                                 {
575                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
576                                         f++;
577                                 }
578                         }
579                         else
580                         {
581                                 for (j = x;j >= y;j--)
582                                 {
583                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
584                                         f++;
585                                 }
586                         }
587                         f = 1.0f / f;
588                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
589                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
590                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
591                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
592                 }
593         }
594         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
595 }
596
597 //=======================================================================================================================================================
598
599 static const char *builtinshaderstring =
600 #include "shader_glsl.h"
601 ;
602
603 const char *builtinhlslshaderstring =
604 #include "shader_hlsl.h"
605 ;
606
607 char *glslshaderstring = NULL;
608 char *hlslshaderstring = NULL;
609
610 //=======================================================================================================================================================
611
612 typedef struct shaderpermutationinfo_s
613 {
614         const char *pretext;
615         const char *name;
616 }
617 shaderpermutationinfo_t;
618
619 typedef struct shadermodeinfo_s
620 {
621         const char *vertexfilename;
622         const char *geometryfilename;
623         const char *fragmentfilename;
624         const char *pretext;
625         const char *name;
626 }
627 shadermodeinfo_t;
628
629 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
630 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
631 {
632         {"#define USEDIFFUSE\n", " diffuse"},
633         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
634         {"#define USEVIEWTINT\n", " viewtint"},
635         {"#define USECOLORMAPPING\n", " colormapping"},
636         {"#define USESATURATION\n", " saturation"},
637         {"#define USEFOGINSIDE\n", " foginside"},
638         {"#define USEFOGOUTSIDE\n", " fogoutside"},
639         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
640         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
641         {"#define USEGAMMARAMPS\n", " gammaramps"},
642         {"#define USECUBEFILTER\n", " cubefilter"},
643         {"#define USEGLOW\n", " glow"},
644         {"#define USEBLOOM\n", " bloom"},
645         {"#define USESPECULAR\n", " specular"},
646         {"#define USEPOSTPROCESSING\n", " postprocessing"},
647         {"#define USEREFLECTION\n", " reflection"},
648         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
649         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
650         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
651         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
652         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
653         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
654         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
655         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
656         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
657         {"#define USEALPHAKILL\n", " alphakill"},
658         {"#define USEREFLECTCUBE\n", " reflectcube"},
659         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
660         {"#define USEBOUNCEGRID\n", " bouncegrid"},
661         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
662 };
663
664 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
665 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
666 {
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
669         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
683 };
684
685 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
686 {
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
703 };
704
705 struct r_glsl_permutation_s;
706 typedef struct r_glsl_permutation_s
707 {
708         /// hash lookup data
709         struct r_glsl_permutation_s *hashnext;
710         unsigned int mode;
711         unsigned int permutation;
712
713         /// indicates if we have tried compiling this permutation already
714         qboolean compiled;
715         /// 0 if compilation failed
716         int program;
717         // texture units assigned to each detected uniform
718         int tex_Texture_First;
719         int tex_Texture_Second;
720         int tex_Texture_GammaRamps;
721         int tex_Texture_Normal;
722         int tex_Texture_Color;
723         int tex_Texture_Gloss;
724         int tex_Texture_Glow;
725         int tex_Texture_SecondaryNormal;
726         int tex_Texture_SecondaryColor;
727         int tex_Texture_SecondaryGloss;
728         int tex_Texture_SecondaryGlow;
729         int tex_Texture_Pants;
730         int tex_Texture_Shirt;
731         int tex_Texture_FogHeightTexture;
732         int tex_Texture_FogMask;
733         int tex_Texture_Lightmap;
734         int tex_Texture_Deluxemap;
735         int tex_Texture_Attenuation;
736         int tex_Texture_Cube;
737         int tex_Texture_Refraction;
738         int tex_Texture_Reflection;
739         int tex_Texture_ShadowMap2D;
740         int tex_Texture_CubeProjection;
741         int tex_Texture_ScreenDepth;
742         int tex_Texture_ScreenNormalMap;
743         int tex_Texture_ScreenDiffuse;
744         int tex_Texture_ScreenSpecular;
745         int tex_Texture_ReflectMask;
746         int tex_Texture_ReflectCube;
747         int tex_Texture_BounceGrid;
748         /// locations of detected uniforms in program object, or -1 if not found
749         int loc_Texture_First;
750         int loc_Texture_Second;
751         int loc_Texture_GammaRamps;
752         int loc_Texture_Normal;
753         int loc_Texture_Color;
754         int loc_Texture_Gloss;
755         int loc_Texture_Glow;
756         int loc_Texture_SecondaryNormal;
757         int loc_Texture_SecondaryColor;
758         int loc_Texture_SecondaryGloss;
759         int loc_Texture_SecondaryGlow;
760         int loc_Texture_Pants;
761         int loc_Texture_Shirt;
762         int loc_Texture_FogHeightTexture;
763         int loc_Texture_FogMask;
764         int loc_Texture_Lightmap;
765         int loc_Texture_Deluxemap;
766         int loc_Texture_Attenuation;
767         int loc_Texture_Cube;
768         int loc_Texture_Refraction;
769         int loc_Texture_Reflection;
770         int loc_Texture_ShadowMap2D;
771         int loc_Texture_CubeProjection;
772         int loc_Texture_ScreenDepth;
773         int loc_Texture_ScreenNormalMap;
774         int loc_Texture_ScreenDiffuse;
775         int loc_Texture_ScreenSpecular;
776         int loc_Texture_ReflectMask;
777         int loc_Texture_ReflectCube;
778         int loc_Texture_BounceGrid;
779         int loc_Alpha;
780         int loc_BloomBlur_Parameters;
781         int loc_ClientTime;
782         int loc_Color_Ambient;
783         int loc_Color_Diffuse;
784         int loc_Color_Specular;
785         int loc_Color_Glow;
786         int loc_Color_Pants;
787         int loc_Color_Shirt;
788         int loc_DeferredColor_Ambient;
789         int loc_DeferredColor_Diffuse;
790         int loc_DeferredColor_Specular;
791         int loc_DeferredMod_Diffuse;
792         int loc_DeferredMod_Specular;
793         int loc_DistortScaleRefractReflect;
794         int loc_EyePosition;
795         int loc_FogColor;
796         int loc_FogHeightFade;
797         int loc_FogPlane;
798         int loc_FogPlaneViewDist;
799         int loc_FogRangeRecip;
800         int loc_LightColor;
801         int loc_LightDir;
802         int loc_LightPosition;
803         int loc_OffsetMapping_ScaleSteps;
804         int loc_PixelSize;
805         int loc_ReflectColor;
806         int loc_ReflectFactor;
807         int loc_ReflectOffset;
808         int loc_RefractColor;
809         int loc_Saturation;
810         int loc_ScreenCenterRefractReflect;
811         int loc_ScreenScaleRefractReflect;
812         int loc_ScreenToDepth;
813         int loc_ShadowMap_Parameters;
814         int loc_ShadowMap_TextureScale;
815         int loc_SpecularPower;
816         int loc_UserVec1;
817         int loc_UserVec2;
818         int loc_UserVec3;
819         int loc_UserVec4;
820         int loc_ViewTintColor;
821         int loc_ViewToLight;
822         int loc_ModelToLight;
823         int loc_TexMatrix;
824         int loc_BackgroundTexMatrix;
825         int loc_ModelViewProjectionMatrix;
826         int loc_ModelViewMatrix;
827         int loc_PixelToScreenTexCoord;
828         int loc_ModelToReflectCube;
829         int loc_ShadowMapMatrix;
830         int loc_BloomColorSubtract;
831         int loc_NormalmapScrollBlend;
832         int loc_BounceGridMatrix;
833         int loc_BounceGridIntensity;
834 }
835 r_glsl_permutation_t;
836
837 #define SHADERPERMUTATION_HASHSIZE 256
838
839
840 // non-degradable "lightweight" shader parameters to keep the permutations simpler
841 // these can NOT degrade! only use for simple stuff
842 enum
843 {
844         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
845         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
846         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
847         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
850         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
851 };
852 #define SHADERSTATICPARMS_COUNT 7
853
854 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
855 static int shaderstaticparms_count = 0;
856
857 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
858 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
859 qboolean R_CompileShader_CheckStaticParms(void)
860 {
861         static int r_compileshader_staticparms_save[1];
862         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
863         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
864
865         // detect all
866         if (r_glsl_saturation_redcompensate.integer)
867                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
868         if (r_glsl_vertextextureblend_usebothalphas.integer)
869                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
870         if (r_shadow_glossexact.integer)
871                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
872         if (r_glsl_postprocess.integer)
873         {
874                 if (r_glsl_postprocess_uservec1_enable.integer)
875                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
876                 if (r_glsl_postprocess_uservec2_enable.integer)
877                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
878                 if (r_glsl_postprocess_uservec3_enable.integer)
879                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
880                 if (r_glsl_postprocess_uservec4_enable.integer)
881                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
882         }
883         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
884 }
885
886 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
887         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
888                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
889         else \
890                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
891 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
892 {
893         shaderstaticparms_count = 0;
894
895         // emit all
896         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
897         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
898         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
899         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
900         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
901         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
902         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
903 }
904
905 /// information about each possible shader permutation
906 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
907 /// currently selected permutation
908 r_glsl_permutation_t *r_glsl_permutation;
909 /// storage for permutations linked in the hash table
910 memexpandablearray_t r_glsl_permutationarray;
911
912 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
913 {
914         //unsigned int hashdepth = 0;
915         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
916         r_glsl_permutation_t *p;
917         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
918         {
919                 if (p->mode == mode && p->permutation == permutation)
920                 {
921                         //if (hashdepth > 10)
922                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
923                         return p;
924                 }
925                 //hashdepth++;
926         }
927         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
928         p->mode = mode;
929         p->permutation = permutation;
930         p->hashnext = r_glsl_permutationhash[mode][hashindex];
931         r_glsl_permutationhash[mode][hashindex] = p;
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
937 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
938 {
939         char *shaderstring;
940         if (!filename || !filename[0])
941                 return NULL;
942         if (!strcmp(filename, "glsl/default.glsl"))
943         {
944                 if (!glslshaderstring)
945                 {
946                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
947                         if (glslshaderstring)
948                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
949                         else
950                                 glslshaderstring = (char *)builtinshaderstring;
951                 }
952                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
953                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
954                 return shaderstring;
955         }
956         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
957         if (shaderstring)
958         {
959                 if (printfromdisknotice)
960                         Con_DPrintf("from disk %s... ", filename);
961                 return shaderstring;
962         }
963         return shaderstring;
964 }
965
966 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
967 {
968         int i;
969         int sampler;
970         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
971         char *vertexstring, *geometrystring, *fragmentstring;
972         char permutationname[256];
973         int vertstrings_count = 0;
974         int geomstrings_count = 0;
975         int fragstrings_count = 0;
976         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
977         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
978         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
979
980         if (p->compiled)
981                 return;
982         p->compiled = true;
983         p->program = 0;
984
985         permutationname[0] = 0;
986         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
987         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
988         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
989
990         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
991
992         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
993         if(vid.support.gl20shaders130)
994         {
995                 vertstrings_list[vertstrings_count++] = "#version 130\n";
996                 geomstrings_list[geomstrings_count++] = "#version 130\n";
997                 fragstrings_list[fragstrings_count++] = "#version 130\n";
998                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
999                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1000                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1001         }
1002
1003         // the first pretext is which type of shader to compile as
1004         // (later these will all be bound together as a program object)
1005         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1006         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1007         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1008
1009         // the second pretext is the mode (for example a light source)
1010         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1011         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1012         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1013         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1014
1015         // now add all the permutation pretexts
1016         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1017         {
1018                 if (permutation & (1<<i))
1019                 {
1020                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1021                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1022                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1023                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1024                 }
1025                 else
1026                 {
1027                         // keep line numbers correct
1028                         vertstrings_list[vertstrings_count++] = "\n";
1029                         geomstrings_list[geomstrings_count++] = "\n";
1030                         fragstrings_list[fragstrings_count++] = "\n";
1031                 }
1032         }
1033
1034         // add static parms
1035         R_CompileShader_AddStaticParms(mode, permutation);
1036         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1037         vertstrings_count += shaderstaticparms_count;
1038         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1039         geomstrings_count += shaderstaticparms_count;
1040         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1041         fragstrings_count += shaderstaticparms_count;
1042
1043         // now append the shader text itself
1044         vertstrings_list[vertstrings_count++] = vertexstring;
1045         geomstrings_list[geomstrings_count++] = geometrystring;
1046         fragstrings_list[fragstrings_count++] = fragmentstring;
1047
1048         // if any sources were NULL, clear the respective list
1049         if (!vertexstring)
1050                 vertstrings_count = 0;
1051         if (!geometrystring)
1052                 geomstrings_count = 0;
1053         if (!fragmentstring)
1054                 fragstrings_count = 0;
1055
1056         // compile the shader program
1057         if (vertstrings_count + geomstrings_count + fragstrings_count)
1058                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1059         if (p->program)
1060         {
1061                 CHECKGLERROR
1062                 qglUseProgram(p->program);CHECKGLERROR
1063                 // look up all the uniform variable names we care about, so we don't
1064                 // have to look them up every time we set them
1065
1066                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1067                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1068                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1069                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1070                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1071                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1072                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1073                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1074                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1075                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1076                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1077                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1078                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1079                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1080                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1081                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1082                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1083                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1084                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1085                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1086                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1087                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1088                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1089                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1090                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1091                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1092                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1093                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1094                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1095                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1096                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1097                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1098                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1099                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1100                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1101                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1102                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1103                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1104                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1105                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1106                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1107                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1108                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1109                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1110                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1111                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1112                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1113                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1114                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1115                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1116                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1117                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1118                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1119                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1120                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1121                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1122                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1123                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1124                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1125                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1126                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1127                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1128                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1129                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1130                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1131                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1132                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1133                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1134                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1135                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1136                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1137                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1138                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1139                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1140                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1141                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1142                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1143                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1144                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1145                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1146                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1147                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1148                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1149                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1150                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1151                 // initialize the samplers to refer to the texture units we use
1152                 p->tex_Texture_First = -1;
1153                 p->tex_Texture_Second = -1;
1154                 p->tex_Texture_GammaRamps = -1;
1155                 p->tex_Texture_Normal = -1;
1156                 p->tex_Texture_Color = -1;
1157                 p->tex_Texture_Gloss = -1;
1158                 p->tex_Texture_Glow = -1;
1159                 p->tex_Texture_SecondaryNormal = -1;
1160                 p->tex_Texture_SecondaryColor = -1;
1161                 p->tex_Texture_SecondaryGloss = -1;
1162                 p->tex_Texture_SecondaryGlow = -1;
1163                 p->tex_Texture_Pants = -1;
1164                 p->tex_Texture_Shirt = -1;
1165                 p->tex_Texture_FogHeightTexture = -1;
1166                 p->tex_Texture_FogMask = -1;
1167                 p->tex_Texture_Lightmap = -1;
1168                 p->tex_Texture_Deluxemap = -1;
1169                 p->tex_Texture_Attenuation = -1;
1170                 p->tex_Texture_Cube = -1;
1171                 p->tex_Texture_Refraction = -1;
1172                 p->tex_Texture_Reflection = -1;
1173                 p->tex_Texture_ShadowMap2D = -1;
1174                 p->tex_Texture_CubeProjection = -1;
1175                 p->tex_Texture_ScreenDepth = -1;
1176                 p->tex_Texture_ScreenNormalMap = -1;
1177                 p->tex_Texture_ScreenDiffuse = -1;
1178                 p->tex_Texture_ScreenSpecular = -1;
1179                 p->tex_Texture_ReflectMask = -1;
1180                 p->tex_Texture_ReflectCube = -1;
1181                 p->tex_Texture_BounceGrid = -1;
1182                 sampler = 0;
1183                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1184                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1185                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1186                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1187                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1188                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1189                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1190                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1191                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1192                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1193                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1194                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1195                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1196                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1197                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1198                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1199                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1200                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1201                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1202                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1203                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1204                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1205                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1206                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1207                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1208                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1209                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1210                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1211                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1212                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1213                 CHECKGLERROR
1214                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1215         }
1216         else
1217                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1218
1219         // free the strings
1220         if (vertexstring)
1221                 Mem_Free(vertexstring);
1222         if (geometrystring)
1223                 Mem_Free(geometrystring);
1224         if (fragmentstring)
1225                 Mem_Free(fragmentstring);
1226 }
1227
1228 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1229 {
1230         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1231         if (r_glsl_permutation != perm)
1232         {
1233                 r_glsl_permutation = perm;
1234                 if (!r_glsl_permutation->program)
1235                 {
1236                         if (!r_glsl_permutation->compiled)
1237                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1238                         if (!r_glsl_permutation->program)
1239                         {
1240                                 // remove features until we find a valid permutation
1241                                 int i;
1242                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1243                                 {
1244                                         // reduce i more quickly whenever it would not remove any bits
1245                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1246                                         if (!(permutation & j))
1247                                                 continue;
1248                                         permutation -= j;
1249                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1250                                         if (!r_glsl_permutation->compiled)
1251                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1252                                         if (r_glsl_permutation->program)
1253                                                 break;
1254                                 }
1255                                 if (i >= SHADERPERMUTATION_COUNT)
1256                                 {
1257                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1258                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1259                                         qglUseProgram(0);CHECKGLERROR
1260                                         return; // no bit left to clear, entire mode is broken
1261                                 }
1262                         }
1263                 }
1264                 CHECKGLERROR
1265                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1266         }
1267         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1268         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1269         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1270 }
1271
1272 #ifdef SUPPORTD3D
1273
1274 #ifdef SUPPORTD3D
1275 #include <d3d9.h>
1276 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1277 extern D3DCAPS9 vid_d3d9caps;
1278 #endif
1279
1280 struct r_hlsl_permutation_s;
1281 typedef struct r_hlsl_permutation_s
1282 {
1283         /// hash lookup data
1284         struct r_hlsl_permutation_s *hashnext;
1285         unsigned int mode;
1286         unsigned int permutation;
1287
1288         /// indicates if we have tried compiling this permutation already
1289         qboolean compiled;
1290         /// NULL if compilation failed
1291         IDirect3DVertexShader9 *vertexshader;
1292         IDirect3DPixelShader9 *pixelshader;
1293 }
1294 r_hlsl_permutation_t;
1295
1296 typedef enum D3DVSREGISTER_e
1297 {
1298         D3DVSREGISTER_TexMatrix = 0, // float4x4
1299         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1300         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1301         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1302         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1303         D3DVSREGISTER_ModelToLight = 20, // float4x4
1304         D3DVSREGISTER_EyePosition = 24,
1305         D3DVSREGISTER_FogPlane = 25,
1306         D3DVSREGISTER_LightDir = 26,
1307         D3DVSREGISTER_LightPosition = 27,
1308 }
1309 D3DVSREGISTER_t;
1310
1311 typedef enum D3DPSREGISTER_e
1312 {
1313         D3DPSREGISTER_Alpha = 0,
1314         D3DPSREGISTER_BloomBlur_Parameters = 1,
1315         D3DPSREGISTER_ClientTime = 2,
1316         D3DPSREGISTER_Color_Ambient = 3,
1317         D3DPSREGISTER_Color_Diffuse = 4,
1318         D3DPSREGISTER_Color_Specular = 5,
1319         D3DPSREGISTER_Color_Glow = 6,
1320         D3DPSREGISTER_Color_Pants = 7,
1321         D3DPSREGISTER_Color_Shirt = 8,
1322         D3DPSREGISTER_DeferredColor_Ambient = 9,
1323         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1324         D3DPSREGISTER_DeferredColor_Specular = 11,
1325         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1326         D3DPSREGISTER_DeferredMod_Specular = 13,
1327         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1328         D3DPSREGISTER_EyePosition = 15, // unused
1329         D3DPSREGISTER_FogColor = 16,
1330         D3DPSREGISTER_FogHeightFade = 17,
1331         D3DPSREGISTER_FogPlane = 18,
1332         D3DPSREGISTER_FogPlaneViewDist = 19,
1333         D3DPSREGISTER_FogRangeRecip = 20,
1334         D3DPSREGISTER_LightColor = 21,
1335         D3DPSREGISTER_LightDir = 22, // unused
1336         D3DPSREGISTER_LightPosition = 23,
1337         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1338         D3DPSREGISTER_PixelSize = 25,
1339         D3DPSREGISTER_ReflectColor = 26,
1340         D3DPSREGISTER_ReflectFactor = 27,
1341         D3DPSREGISTER_ReflectOffset = 28,
1342         D3DPSREGISTER_RefractColor = 29,
1343         D3DPSREGISTER_Saturation = 30,
1344         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1345         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1346         D3DPSREGISTER_ScreenToDepth = 33,
1347         D3DPSREGISTER_ShadowMap_Parameters = 34,
1348         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1349         D3DPSREGISTER_SpecularPower = 36,
1350         D3DPSREGISTER_UserVec1 = 37,
1351         D3DPSREGISTER_UserVec2 = 38,
1352         D3DPSREGISTER_UserVec3 = 39,
1353         D3DPSREGISTER_UserVec4 = 40,
1354         D3DPSREGISTER_ViewTintColor = 41,
1355         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1356         D3DPSREGISTER_BloomColorSubtract = 43,
1357         D3DPSREGISTER_ViewToLight = 44, // float4x4
1358         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1359         D3DPSREGISTER_NormalmapScrollBlend = 52,
1360         // next at 53
1361 }
1362 D3DPSREGISTER_t;
1363
1364 /// information about each possible shader permutation
1365 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1366 /// currently selected permutation
1367 r_hlsl_permutation_t *r_hlsl_permutation;
1368 /// storage for permutations linked in the hash table
1369 memexpandablearray_t r_hlsl_permutationarray;
1370
1371 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1372 {
1373         //unsigned int hashdepth = 0;
1374         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1375         r_hlsl_permutation_t *p;
1376         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1377         {
1378                 if (p->mode == mode && p->permutation == permutation)
1379                 {
1380                         //if (hashdepth > 10)
1381                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1382                         return p;
1383                 }
1384                 //hashdepth++;
1385         }
1386         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1387         p->mode = mode;
1388         p->permutation = permutation;
1389         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1390         r_hlsl_permutationhash[mode][hashindex] = p;
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
1396 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1397 {
1398         char *shaderstring;
1399         if (!filename || !filename[0])
1400                 return NULL;
1401         if (!strcmp(filename, "hlsl/default.hlsl"))
1402         {
1403                 if (!hlslshaderstring)
1404                 {
1405                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1406                         if (hlslshaderstring)
1407                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1408                         else
1409                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1410                 }
1411                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1412                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1413                 return shaderstring;
1414         }
1415         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1416         if (shaderstring)
1417         {
1418                 if (printfromdisknotice)
1419                         Con_DPrintf("from disk %s... ", filename);
1420                 return shaderstring;
1421         }
1422         return shaderstring;
1423 }
1424
1425 #include <d3dx9.h>
1426 //#include <d3dx9shader.h>
1427 //#include <d3dx9mesh.h>
1428
1429 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1430 {
1431         DWORD *vsbin = NULL;
1432         DWORD *psbin = NULL;
1433         fs_offset_t vsbinsize;
1434         fs_offset_t psbinsize;
1435 //      IDirect3DVertexShader9 *vs = NULL;
1436 //      IDirect3DPixelShader9 *ps = NULL;
1437         ID3DXBuffer *vslog = NULL;
1438         ID3DXBuffer *vsbuffer = NULL;
1439         ID3DXConstantTable *vsconstanttable = NULL;
1440         ID3DXBuffer *pslog = NULL;
1441         ID3DXBuffer *psbuffer = NULL;
1442         ID3DXConstantTable *psconstanttable = NULL;
1443         int vsresult = 0;
1444         int psresult = 0;
1445         char temp[MAX_INPUTLINE];
1446         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1447         qboolean debugshader = gl_paranoid.integer != 0;
1448         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1449         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1450         if (!debugshader)
1451         {
1452                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1453                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1454         }
1455         if ((!vsbin && vertstring) || (!psbin && fragstring))
1456         {
1457                 const char* dllnames_d3dx9 [] =
1458                 {
1459                         "d3dx9_43.dll",
1460                         "d3dx9_42.dll",
1461                         "d3dx9_41.dll",
1462                         "d3dx9_40.dll",
1463                         "d3dx9_39.dll",
1464                         "d3dx9_38.dll",
1465                         "d3dx9_37.dll",
1466                         "d3dx9_36.dll",
1467                         "d3dx9_35.dll",
1468                         "d3dx9_34.dll",
1469                         "d3dx9_33.dll",
1470                         "d3dx9_32.dll",
1471                         "d3dx9_31.dll",
1472                         "d3dx9_30.dll",
1473                         "d3dx9_29.dll",
1474                         "d3dx9_28.dll",
1475                         "d3dx9_27.dll",
1476                         "d3dx9_26.dll",
1477                         "d3dx9_25.dll",
1478                         "d3dx9_24.dll",
1479                         NULL
1480                 };
1481                 dllhandle_t d3dx9_dll = NULL;
1482                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1483                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1484                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1485                 dllfunction_t d3dx9_dllfuncs[] =
1486                 {
1487                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1488                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1489                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1490                         {NULL, NULL}
1491                 };
1492                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1493                 {
1494                         DWORD shaderflags = 0;
1495                         if (debugshader)
1496                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1497                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1498                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1499                         if (vertstring && vertstring[0])
1500                         {
1501                                 if (debugshader)
1502                                 {
1503 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1504 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1505                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1506                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1507                                 }
1508                                 else
1509                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1510                                 if (vsbuffer)
1511                                 {
1512                                         vsbinsize = vsbuffer->GetBufferSize();
1513                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1514                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1515                                         vsbuffer->Release();
1516                                 }
1517                                 if (vslog)
1518                                 {
1519                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1520                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1521                                         vslog->Release();
1522                                 }
1523                         }
1524                         if (fragstring && fragstring[0])
1525                         {
1526                                 if (debugshader)
1527                                 {
1528 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1529 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1530                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1531                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1532                                 }
1533                                 else
1534                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1535                                 if (psbuffer)
1536                                 {
1537                                         psbinsize = psbuffer->GetBufferSize();
1538                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1539                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1540                                         psbuffer->Release();
1541                                 }
1542                                 if (pslog)
1543                                 {
1544                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1545                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1546                                         pslog->Release();
1547                                 }
1548                         }
1549                         Sys_UnloadLibrary(&d3dx9_dll);
1550                 }
1551                 else
1552                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1553         }
1554         if (vsbin && psbin)
1555         {
1556                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1557                 if (FAILED(vsresult))
1558                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1559                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1560                 if (FAILED(psresult))
1561                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1562         }
1563         // free the shader data
1564         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1565         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1566 }
1567
1568 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1569 {
1570         int i;
1571         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1572         int vertstring_length = 0;
1573         int geomstring_length = 0;
1574         int fragstring_length = 0;
1575         char *t;
1576         char *vertexstring, *geometrystring, *fragmentstring;
1577         char *vertstring, *geomstring, *fragstring;
1578         char permutationname[256];
1579         char cachename[256];
1580         int vertstrings_count = 0;
1581         int geomstrings_count = 0;
1582         int fragstrings_count = 0;
1583         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1584         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1585         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1586
1587         if (p->compiled)
1588                 return;
1589         p->compiled = true;
1590         p->vertexshader = NULL;
1591         p->pixelshader = NULL;
1592
1593         permutationname[0] = 0;
1594         cachename[0] = 0;
1595         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1596         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1597         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1598
1599         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1600         strlcat(cachename, "hlsl/", sizeof(cachename));
1601
1602         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1603         vertstrings_count = 0;
1604         geomstrings_count = 0;
1605         fragstrings_count = 0;
1606         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1607         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1608         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1609
1610         // the first pretext is which type of shader to compile as
1611         // (later these will all be bound together as a program object)
1612         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1613         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1614         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1615
1616         // the second pretext is the mode (for example a light source)
1617         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1618         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1619         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1620         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1621         strlcat(cachename, modeinfo->name, sizeof(cachename));
1622
1623         // now add all the permutation pretexts
1624         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1625         {
1626                 if (permutation & (1<<i))
1627                 {
1628                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1629                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1630                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1631                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1632                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1633                 }
1634                 else
1635                 {
1636                         // keep line numbers correct
1637                         vertstrings_list[vertstrings_count++] = "\n";
1638                         geomstrings_list[geomstrings_count++] = "\n";
1639                         fragstrings_list[fragstrings_count++] = "\n";
1640                 }
1641         }
1642
1643         // add static parms
1644         R_CompileShader_AddStaticParms(mode, permutation);
1645         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1646         vertstrings_count += shaderstaticparms_count;
1647         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1648         geomstrings_count += shaderstaticparms_count;
1649         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1650         fragstrings_count += shaderstaticparms_count;
1651
1652         // replace spaces in the cachename with _ characters
1653         for (i = 0;cachename[i];i++)
1654                 if (cachename[i] == ' ')
1655                         cachename[i] = '_';
1656
1657         // now append the shader text itself
1658         vertstrings_list[vertstrings_count++] = vertexstring;
1659         geomstrings_list[geomstrings_count++] = geometrystring;
1660         fragstrings_list[fragstrings_count++] = fragmentstring;
1661
1662         // if any sources were NULL, clear the respective list
1663         if (!vertexstring)
1664                 vertstrings_count = 0;
1665         if (!geometrystring)
1666                 geomstrings_count = 0;
1667         if (!fragmentstring)
1668                 fragstrings_count = 0;
1669
1670         vertstring_length = 0;
1671         for (i = 0;i < vertstrings_count;i++)
1672                 vertstring_length += strlen(vertstrings_list[i]);
1673         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1674         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1675                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1676
1677         geomstring_length = 0;
1678         for (i = 0;i < geomstrings_count;i++)
1679                 geomstring_length += strlen(geomstrings_list[i]);
1680         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1681         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1682                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1683
1684         fragstring_length = 0;
1685         for (i = 0;i < fragstrings_count;i++)
1686                 fragstring_length += strlen(fragstrings_list[i]);
1687         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1688         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1689                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1690
1691         // try to load the cached shader, or generate one
1692         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1693
1694         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1695                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1696         else
1697                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1698
1699         // free the strings
1700         if (vertstring)
1701                 Mem_Free(vertstring);
1702         if (geomstring)
1703                 Mem_Free(geomstring);
1704         if (fragstring)
1705                 Mem_Free(fragstring);
1706         if (vertexstring)
1707                 Mem_Free(vertexstring);
1708         if (geometrystring)
1709                 Mem_Free(geometrystring);
1710         if (fragmentstring)
1711                 Mem_Free(fragmentstring);
1712 }
1713
1714 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1715 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1716 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);}
1717 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);}
1718 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);}
1719 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);}
1720
1721 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1722 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1723 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);}
1724 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);}
1725 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);}
1726 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);}
1727
1728 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1729 {
1730         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1731         if (r_hlsl_permutation != perm)
1732         {
1733                 r_hlsl_permutation = perm;
1734                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1735                 {
1736                         if (!r_hlsl_permutation->compiled)
1737                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1738                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1739                         {
1740                                 // remove features until we find a valid permutation
1741                                 int i;
1742                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1743                                 {
1744                                         // reduce i more quickly whenever it would not remove any bits
1745                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1746                                         if (!(permutation & j))
1747                                                 continue;
1748                                         permutation -= j;
1749                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1750                                         if (!r_hlsl_permutation->compiled)
1751                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1752                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1753                                                 break;
1754                                 }
1755                                 if (i >= SHADERPERMUTATION_COUNT)
1756                                 {
1757                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1758                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1759                                         return; // no bit left to clear, entire mode is broken
1760                                 }
1761                         }
1762                 }
1763                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1764                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1765         }
1766         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1767         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1768         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1769 }
1770 #endif
1771
1772 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1773 {
1774         DPSOFTRAST_SetShader(mode, permutation);
1775         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1776         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1777         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1778 }
1779
1780 void R_GLSL_Restart_f(void)
1781 {
1782         unsigned int i, limit;
1783         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1784                 Mem_Free(glslshaderstring);
1785         glslshaderstring = NULL;
1786         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1787                 Mem_Free(hlslshaderstring);
1788         hlslshaderstring = NULL;
1789         switch(vid.renderpath)
1790         {
1791         case RENDERPATH_D3D9:
1792 #ifdef SUPPORTD3D
1793                 {
1794                         r_hlsl_permutation_t *p;
1795                         r_hlsl_permutation = NULL;
1796                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1797                         for (i = 0;i < limit;i++)
1798                         {
1799                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1800                                 {
1801                                         if (p->vertexshader)
1802                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1803                                         if (p->pixelshader)
1804                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1805                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1806                                 }
1807                         }
1808                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1809                 }
1810 #endif
1811                 break;
1812         case RENDERPATH_D3D10:
1813                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1814                 break;
1815         case RENDERPATH_D3D11:
1816                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1817                 break;
1818         case RENDERPATH_GL20:
1819         case RENDERPATH_GLES2:
1820                 {
1821                         r_glsl_permutation_t *p;
1822                         r_glsl_permutation = NULL;
1823                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1824                         for (i = 0;i < limit;i++)
1825                         {
1826                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1827                                 {
1828                                         GL_Backend_FreeProgram(p->program);
1829                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1830                                 }
1831                         }
1832                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1833                 }
1834                 break;
1835         case RENDERPATH_GL13:
1836         case RENDERPATH_GL11:
1837                 break;
1838         case RENDERPATH_SOFT:
1839                 break;
1840         }
1841 }
1842
1843 void R_GLSL_DumpShader_f(void)
1844 {
1845         int i;
1846         qfile_t *file;
1847
1848         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1849         if (file)
1850         {
1851                 FS_Print(file, "/* The engine may define the following macros:\n");
1852                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1853                 for (i = 0;i < SHADERMODE_COUNT;i++)
1854                         FS_Print(file, glslshadermodeinfo[i].pretext);
1855                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1856                         FS_Print(file, shaderpermutationinfo[i].pretext);
1857                 FS_Print(file, "*/\n");
1858                 FS_Print(file, builtinshaderstring);
1859                 FS_Close(file);
1860                 Con_Printf("glsl/default.glsl written\n");
1861         }
1862         else
1863                 Con_Printf("failed to write to glsl/default.glsl\n");
1864
1865         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1866         if (file)
1867         {
1868                 FS_Print(file, "/* The engine may define the following macros:\n");
1869                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1870                 for (i = 0;i < SHADERMODE_COUNT;i++)
1871                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1872                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1873                         FS_Print(file, shaderpermutationinfo[i].pretext);
1874                 FS_Print(file, "*/\n");
1875                 FS_Print(file, builtinhlslshaderstring);
1876                 FS_Close(file);
1877                 Con_Printf("hlsl/default.hlsl written\n");
1878         }
1879         else
1880                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1881 }
1882
1883 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1884 {
1885         if (!second)
1886                 texturemode = GL_MODULATE;
1887         switch (vid.renderpath)
1888         {
1889         case RENDERPATH_D3D9:
1890 #ifdef SUPPORTD3D
1891                 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))));
1892                 R_Mesh_TexBind(GL20TU_FIRST , first );
1893                 R_Mesh_TexBind(GL20TU_SECOND, second);
1894 #endif
1895                 break;
1896         case RENDERPATH_D3D10:
1897                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1898                 break;
1899         case RENDERPATH_D3D11:
1900                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1901                 break;
1902         case RENDERPATH_GL20:
1903         case RENDERPATH_GLES2:
1904                 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))));
1905                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1906                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1907                 break;
1908         case RENDERPATH_GL13:
1909                 R_Mesh_TexBind(0, first );
1910                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1911                 R_Mesh_TexBind(1, second);
1912                 if (second)
1913                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1914                 break;
1915         case RENDERPATH_GL11:
1916                 R_Mesh_TexBind(0, first );
1917                 break;
1918         case RENDERPATH_SOFT:
1919                 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))));
1920                 R_Mesh_TexBind(GL20TU_FIRST , first );
1921                 R_Mesh_TexBind(GL20TU_SECOND, second);
1922                 break;
1923         }
1924 }
1925
1926 void R_SetupShader_DepthOrShadow(void)
1927 {
1928         switch (vid.renderpath)
1929         {
1930         case RENDERPATH_D3D9:
1931 #ifdef SUPPORTD3D
1932                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1933 #endif
1934                 break;
1935         case RENDERPATH_D3D10:
1936                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1937                 break;
1938         case RENDERPATH_D3D11:
1939                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1940                 break;
1941         case RENDERPATH_GL20:
1942         case RENDERPATH_GLES2:
1943                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1944                 break;
1945         case RENDERPATH_GL13:
1946                 R_Mesh_TexBind(0, 0);
1947                 R_Mesh_TexBind(1, 0);
1948                 break;
1949         case RENDERPATH_GL11:
1950                 R_Mesh_TexBind(0, 0);
1951                 break;
1952         case RENDERPATH_SOFT:
1953                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1954                 break;
1955         }
1956 }
1957
1958 void R_SetupShader_ShowDepth(void)
1959 {
1960         switch (vid.renderpath)
1961         {
1962         case RENDERPATH_D3D9:
1963 #ifdef SUPPORTHLSL
1964                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1965 #endif
1966                 break;
1967         case RENDERPATH_D3D10:
1968                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1969                 break;
1970         case RENDERPATH_D3D11:
1971                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1972                 break;
1973         case RENDERPATH_GL20:
1974         case RENDERPATH_GLES2:
1975                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1976                 break;
1977         case RENDERPATH_GL13:
1978                 break;
1979         case RENDERPATH_GL11:
1980                 break;
1981         case RENDERPATH_SOFT:
1982                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1983                 break;
1984         }
1985 }
1986
1987 extern qboolean r_shadow_usingdeferredprepass;
1988 extern cvar_t r_shadow_deferred_8bitrange;
1989 extern rtexture_t *r_shadow_attenuationgradienttexture;
1990 extern rtexture_t *r_shadow_attenuation2dtexture;
1991 extern rtexture_t *r_shadow_attenuation3dtexture;
1992 extern qboolean r_shadow_usingshadowmap2d;
1993 extern qboolean r_shadow_usingshadowmaportho;
1994 extern float r_shadow_shadowmap_texturescale[2];
1995 extern float r_shadow_shadowmap_parameters[4];
1996 extern qboolean r_shadow_shadowmapvsdct;
1997 extern qboolean r_shadow_shadowmapsampler;
1998 extern int r_shadow_shadowmappcf;
1999 extern rtexture_t *r_shadow_shadowmap2dtexture;
2000 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2001 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2002 extern matrix4x4_t r_shadow_shadowmapmatrix;
2003 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2004 extern int r_shadow_prepass_width;
2005 extern int r_shadow_prepass_height;
2006 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2007 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2008 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2009 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2010 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2011
2012 #define BLENDFUNC_ALLOWS_COLORMOD      1
2013 #define BLENDFUNC_ALLOWS_FOG           2
2014 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2015 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2016 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2017 static int R_BlendFuncFlags(int src, int dst)
2018 {
2019         int r = 0;
2020
2021         // a blendfunc allows colormod if:
2022         // a) it can never keep the destination pixel invariant, or
2023         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2024         // this is to prevent unintended side effects from colormod
2025
2026         // a blendfunc allows fog if:
2027         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2028         // this is to prevent unintended side effects from fog
2029
2030         // these checks are the output of fogeval.pl
2031
2032         r |= BLENDFUNC_ALLOWS_COLORMOD;
2033         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2034         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2035         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2036         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2037         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2038         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2039         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2040         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2041         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2042         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2043         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2044         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2045         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2046         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2047         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2048         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2049         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2050         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2051         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2052         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2053         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2054
2055         return r;
2056 }
2057
2058 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)
2059 {
2060         // select a permutation of the lighting shader appropriate to this
2061         // combination of texture, entity, light source, and fogging, only use the
2062         // minimum features necessary to avoid wasting rendering time in the
2063         // fragment shader on features that are not being used
2064         unsigned int permutation = 0;
2065         unsigned int mode = 0;
2066         int blendfuncflags;
2067         static float dummy_colormod[3] = {1, 1, 1};
2068         float *colormod = rsurface.colormod;
2069         float m16f[16];
2070         matrix4x4_t tempmatrix;
2071         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2072         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2073                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2074         if (rsurfacepass == RSURFPASS_BACKGROUND)
2075         {
2076                 // distorted background
2077                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2078                 {
2079                         mode = SHADERMODE_WATER;
2080                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2081                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2082                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2083                         {
2084                                 // this is the right thing to do for wateralpha
2085                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2086                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2087                         }
2088                         else
2089                         {
2090                                 // this is the right thing to do for entity alpha
2091                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2092                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2093                         }
2094                 }
2095                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2096                 {
2097                         mode = SHADERMODE_REFRACTION;
2098                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2099                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2100                 }
2101                 else
2102                 {
2103                         mode = SHADERMODE_GENERIC;
2104                         permutation |= SHADERPERMUTATION_DIFFUSE;
2105                         GL_BlendFunc(GL_ONE, GL_ZERO);
2106                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2107                 }
2108         }
2109         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2110         {
2111                 if (r_glsl_offsetmapping.integer)
2112                 {
2113                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2114                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2115                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2116                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2117                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2118                         {
2119                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2120                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2121                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2122                         }
2123                 }
2124                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2125                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2126                 // normalmap (deferred prepass), may use alpha test on diffuse
2127                 mode = SHADERMODE_DEFERREDGEOMETRY;
2128                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2129                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2130                 GL_BlendFunc(GL_ONE, GL_ZERO);
2131                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2132         }
2133         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2134         {
2135                 if (r_glsl_offsetmapping.integer)
2136                 {
2137                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2138                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2139                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2140                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2141                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2142                         {
2143                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2144                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2145                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2146                         }
2147                 }
2148                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2149                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2150                 // light source
2151                 mode = SHADERMODE_LIGHTSOURCE;
2152                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2153                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2154                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2155                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2156                 if (diffusescale > 0)
2157                         permutation |= SHADERPERMUTATION_DIFFUSE;
2158                 if (specularscale > 0)
2159                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2160                 if (r_refdef.fogenabled)
2161                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2162                 if (rsurface.texture->colormapping)
2163                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2164                 if (r_shadow_usingshadowmap2d)
2165                 {
2166                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2167                         if(r_shadow_shadowmapvsdct)
2168                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2169
2170                         if (r_shadow_shadowmapsampler)
2171                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2172                         if (r_shadow_shadowmappcf > 1)
2173                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2174                         else if (r_shadow_shadowmappcf)
2175                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2176                 }
2177                 if (rsurface.texture->reflectmasktexture)
2178                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2179                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2180                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2181         }
2182         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2183         {
2184                 if (r_glsl_offsetmapping.integer)
2185                 {
2186                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2187                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2188                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2189                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2190                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2191                         {
2192                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2193                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2194                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2195                         }
2196                 }
2197                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2198                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2199                 // unshaded geometry (fullbright or ambient model lighting)
2200                 mode = SHADERMODE_FLATCOLOR;
2201                 ambientscale = diffusescale = specularscale = 0;
2202                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2203                         permutation |= SHADERPERMUTATION_GLOW;
2204                 if (r_refdef.fogenabled)
2205                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2206                 if (rsurface.texture->colormapping)
2207                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2208                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2209                 {
2210                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2211                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2212
2213                         if (r_shadow_shadowmapsampler)
2214                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2215                         if (r_shadow_shadowmappcf > 1)
2216                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2217                         else if (r_shadow_shadowmappcf)
2218                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2219                 }
2220                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2221                         permutation |= SHADERPERMUTATION_REFLECTION;
2222                 if (rsurface.texture->reflectmasktexture)
2223                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2224                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2225                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2226         }
2227         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2228         {
2229                 if (r_glsl_offsetmapping.integer)
2230                 {
2231                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2232                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2233                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2234                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2235                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2236                         {
2237                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2238                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2239                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2240                         }
2241                 }
2242                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2243                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2244                 // directional model lighting
2245                 mode = SHADERMODE_LIGHTDIRECTION;
2246                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2247                         permutation |= SHADERPERMUTATION_GLOW;
2248                 permutation |= SHADERPERMUTATION_DIFFUSE;
2249                 if (specularscale > 0)
2250                         permutation |= SHADERPERMUTATION_SPECULAR;
2251                 if (r_refdef.fogenabled)
2252                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2253                 if (rsurface.texture->colormapping)
2254                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2255                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2256                 {
2257                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2258                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2259
2260                         if (r_shadow_shadowmapsampler)
2261                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2262                         if (r_shadow_shadowmappcf > 1)
2263                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2264                         else if (r_shadow_shadowmappcf)
2265                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2266                 }
2267                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2268                         permutation |= SHADERPERMUTATION_REFLECTION;
2269                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2270                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2271                 if (rsurface.texture->reflectmasktexture)
2272                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2273                 if (r_shadow_bouncegridtexture)
2274                 {
2275                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2276                         if (r_shadow_bouncegriddirectional)
2277                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2278                 }
2279                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2280                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2281         }
2282         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2283         {
2284                 if (r_glsl_offsetmapping.integer)
2285                 {
2286                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2287                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2288                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2289                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2290                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2291                         {
2292                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2293                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2294                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2295                         }
2296                 }
2297                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2298                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2299                 // ambient model lighting
2300                 mode = SHADERMODE_LIGHTDIRECTION;
2301                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2302                         permutation |= SHADERPERMUTATION_GLOW;
2303                 if (r_refdef.fogenabled)
2304                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2305                 if (rsurface.texture->colormapping)
2306                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2307                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2308                 {
2309                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2310                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2311
2312                         if (r_shadow_shadowmapsampler)
2313                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2314                         if (r_shadow_shadowmappcf > 1)
2315                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2316                         else if (r_shadow_shadowmappcf)
2317                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2318                 }
2319                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2320                         permutation |= SHADERPERMUTATION_REFLECTION;
2321                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2322                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2323                 if (rsurface.texture->reflectmasktexture)
2324                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2325                 if (r_shadow_bouncegridtexture)
2326                 {
2327                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2328                         if (r_shadow_bouncegriddirectional)
2329                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2330                 }
2331                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2332                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2333         }
2334         else
2335         {
2336                 if (r_glsl_offsetmapping.integer)
2337                 {
2338                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2339                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2340                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2341                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2342                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2343                         {
2344                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2345                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2346                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2347                         }
2348                 }
2349                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2350                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2351                 // lightmapped wall
2352                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2353                         permutation |= SHADERPERMUTATION_GLOW;
2354                 if (r_refdef.fogenabled)
2355                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2356                 if (rsurface.texture->colormapping)
2357                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2358                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2359                 {
2360                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2361                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2362
2363                         if (r_shadow_shadowmapsampler)
2364                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2365                         if (r_shadow_shadowmappcf > 1)
2366                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2367                         else if (r_shadow_shadowmappcf)
2368                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2369                 }
2370                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2371                         permutation |= SHADERPERMUTATION_REFLECTION;
2372                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2373                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2374                 if (rsurface.texture->reflectmasktexture)
2375                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2376                 if (FAKELIGHT_ENABLED)
2377                 {
2378                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2379                         mode = SHADERMODE_FAKELIGHT;
2380                         permutation |= SHADERPERMUTATION_DIFFUSE;
2381                         if (specularscale > 0)
2382                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2383                 }
2384                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2385                 {
2386                         // deluxemapping (light direction texture)
2387                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2388                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2389                         else
2390                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2391                         permutation |= SHADERPERMUTATION_DIFFUSE;
2392                         if (specularscale > 0)
2393                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2394                 }
2395                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2396                 {
2397                         // fake deluxemapping (uniform light direction in tangentspace)
2398                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2399                         permutation |= SHADERPERMUTATION_DIFFUSE;
2400                         if (specularscale > 0)
2401                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2402                 }
2403                 else if (rsurface.uselightmaptexture)
2404                 {
2405                         // ordinary lightmapping (q1bsp, q3bsp)
2406                         mode = SHADERMODE_LIGHTMAP;
2407                 }
2408                 else
2409                 {
2410                         // ordinary vertex coloring (q3bsp)
2411                         mode = SHADERMODE_VERTEXCOLOR;
2412                 }
2413                 if (r_shadow_bouncegridtexture)
2414                 {
2415                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2416                         if (r_shadow_bouncegriddirectional)
2417                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2418                 }
2419                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2420                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421         }
2422         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2423                 colormod = dummy_colormod;
2424         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2425                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2426         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2427                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2428         switch(vid.renderpath)
2429         {
2430         case RENDERPATH_D3D9:
2431 #ifdef SUPPORTD3D
2432                 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);
2433                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2434                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2435                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2436                 if (mode == SHADERMODE_LIGHTSOURCE)
2437                 {
2438                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2439                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2440                 }
2441                 else
2442                 {
2443                         if (mode == SHADERMODE_LIGHTDIRECTION)
2444                         {
2445                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2446                         }
2447                 }
2448                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2449                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2450                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2451                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2452                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2453
2454                 if (mode == SHADERMODE_LIGHTSOURCE)
2455                 {
2456                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2457                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2458                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2459                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2460                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2461
2462                         // additive passes are only darkened by fog, not tinted
2463                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2464                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2465                 }
2466                 else
2467                 {
2468                         if (mode == SHADERMODE_FLATCOLOR)
2469                         {
2470                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2471                         }
2472                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2473                         {
2474                                 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]);
2475                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2476                                 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);
2477                                 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);
2478                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2479                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2480                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2481                         }
2482                         else
2483                         {
2484                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2485                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2486                                 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);
2487                                 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);
2488                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2489                         }
2490                         // additive passes are only darkened by fog, not tinted
2491                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2492                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2493                         else
2494                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2495                         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);
2496                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2497                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2498                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2499                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2500                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2501                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2502                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2503                         if (mode == SHADERMODE_WATER)
2504                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2505                 }
2506                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2507                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2508                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2509                 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));
2510                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2511                 if (rsurface.texture->pantstexture)
2512                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2513                 else
2514                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2515                 if (rsurface.texture->shirttexture)
2516                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2517                 else
2518                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2519                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2520                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2521                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2522                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2523                 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));
2524                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2525                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2526
2527                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2528                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2529                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2530                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2531                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2532                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2533                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2534                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2535                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2536                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2537                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2538                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2539                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2540                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2541                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2542                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2543                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2544                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2545                 {
2546                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2547                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2548                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2549                 }
2550                 else
2551                 {
2552                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2553                 }
2554 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2555 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2556                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2557                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2558                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2559                 {
2560                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2561                         if (rsurface.rtlight)
2562                         {
2563                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2564                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2565                         }
2566                 }
2567 #endif
2568                 break;
2569         case RENDERPATH_D3D10:
2570                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2571                 break;
2572         case RENDERPATH_D3D11:
2573                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2574                 break;
2575         case RENDERPATH_GL20:
2576         case RENDERPATH_GLES2:
2577                 if (!vid.useinterleavedarrays)
2578                 {
2579                         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);
2580                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2581                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2582                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2583                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2584                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2585                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2586                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2587                 }
2588                 else
2589                 {
2590                         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);
2591                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2592                 }
2593                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2594                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2595                 if (mode == SHADERMODE_LIGHTSOURCE)
2596                 {
2597                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2598                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2599                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2600                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2601                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2602                         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);
2603         
2604                         // additive passes are only darkened by fog, not tinted
2605                         if (r_glsl_permutation->loc_FogColor >= 0)
2606                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2607                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2608                 }
2609                 else
2610                 {
2611                         if (mode == SHADERMODE_FLATCOLOR)
2612                         {
2613                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2614                         }
2615                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2616                         {
2617                                 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]);
2618                                 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]);
2619                                 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);
2620                                 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);
2621                                 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);
2622                                 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]);
2623                                 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]);
2624                         }
2625                         else
2626                         {
2627                                 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]);
2628                                 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]);
2629                                 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);
2630                                 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);
2631                                 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);
2632                         }
2633                         // additive passes are only darkened by fog, not tinted
2634                         if (r_glsl_permutation->loc_FogColor >= 0)
2635                         {
2636                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2637                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2638                                 else
2639                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2640                         }
2641                         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);
2642                         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]);
2643                         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]);
2644                         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]);
2645                         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]);
2646                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2647                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2648                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2649                         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]);
2650                 }
2651                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2652                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2653                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2654                 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]);
2655                 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]);
2656
2657                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2658                 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));
2659                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2660                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2661                 {
2662                         if (rsurface.texture->pantstexture)
2663                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2664                         else
2665                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2666                 }
2667                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2668                 {
2669                         if (rsurface.texture->shirttexture)
2670                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2671                         else
2672                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2673                 }
2674                 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]);
2675                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2676                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2677                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2678                 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));
2679                 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]);
2680                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2681                 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);}
2682                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2683
2684                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2685                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2686                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2687                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2688                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2689                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2690                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2691                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2692                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2693                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2694                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2695                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2696                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2697                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2698                 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);
2699                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2700                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2701                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2702                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2703                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2704                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2705                 {
2706                         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);
2707                         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);
2708                         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);
2709                 }
2710                 else
2711                 {
2712                         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);
2713                 }
2714                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2715                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2716                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2717                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2718                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2719                 {
2720                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2721                         if (rsurface.rtlight)
2722                         {
2723                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2724                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2725                         }
2726                 }
2727                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2728                 CHECKGLERROR
2729                 break;
2730         case RENDERPATH_GL13:
2731         case RENDERPATH_GL11:
2732                 break;
2733         case RENDERPATH_SOFT:
2734                 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);
2735                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2736                 R_SetupShader_SetPermutationSoft(mode, permutation);
2737                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2738                 if (mode == SHADERMODE_LIGHTSOURCE)
2739                 {
2740                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2741                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2742                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2743                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2744                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2745                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2746         
2747                         // additive passes are only darkened by fog, not tinted
2748                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2749                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2750                 }
2751                 else
2752                 {
2753                         if (mode == SHADERMODE_FLATCOLOR)
2754                         {
2755                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2756                         }
2757                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2758                         {
2759                                 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]);
2760                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2761                                 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);
2762                                 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);
2763                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2764                                 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]);
2765                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2766                         }
2767                         else
2768                         {
2769                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2770                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2771                                 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);
2772                                 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);
2773                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2774                         }
2775                         // additive passes are only darkened by fog, not tinted
2776                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2777                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2778                         else
2779                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2780                         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);
2781                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2782                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2783                         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]);
2784                         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]);
2785                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2786                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2787                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2788                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2789                 }
2790                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2791                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2792                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2793                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2794                 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]);
2795
2796                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2797                 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));
2798                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2799                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2800                 {
2801                         if (rsurface.texture->pantstexture)
2802                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2803                         else
2804                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2805                 }
2806                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2807                 {
2808                         if (rsurface.texture->shirttexture)
2809                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2810                         else
2811                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2812                 }
2813                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2814                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2815                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2816                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2817                 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));
2818                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2819                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2820
2821                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2822                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2823                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2824                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2825                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2826                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2827                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2828                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2829                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2830                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2831                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2832                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2833                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2834                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2835                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2836                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2837                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2838                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2839                 {
2840                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2841                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2842                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2843                 }
2844                 else
2845                 {
2846                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2847                 }
2848 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2849 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2850                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2851                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2852                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2853                 {
2854                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2855                         if (rsurface.rtlight)
2856                         {
2857                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2858                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2859                         }
2860                 }
2861                 break;
2862         }
2863 }
2864
2865 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2866 {
2867         // select a permutation of the lighting shader appropriate to this
2868         // combination of texture, entity, light source, and fogging, only use the
2869         // minimum features necessary to avoid wasting rendering time in the
2870         // fragment shader on features that are not being used
2871         unsigned int permutation = 0;
2872         unsigned int mode = 0;
2873         const float *lightcolorbase = rtlight->currentcolor;
2874         float ambientscale = rtlight->ambientscale;
2875         float diffusescale = rtlight->diffusescale;
2876         float specularscale = rtlight->specularscale;
2877         // this is the location of the light in view space
2878         vec3_t viewlightorigin;
2879         // this transforms from view space (camera) to light space (cubemap)
2880         matrix4x4_t viewtolight;
2881         matrix4x4_t lighttoview;
2882         float viewtolight16f[16];
2883         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2884         // light source
2885         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2886         if (rtlight->currentcubemap != r_texture_whitecube)
2887                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2888         if (diffusescale > 0)
2889                 permutation |= SHADERPERMUTATION_DIFFUSE;
2890         if (specularscale > 0)
2891                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2892         if (r_shadow_usingshadowmap2d)
2893         {
2894                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2895                 if (r_shadow_shadowmapvsdct)
2896                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2897
2898                 if (r_shadow_shadowmapsampler)
2899                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2900                 if (r_shadow_shadowmappcf > 1)
2901                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2902                 else if (r_shadow_shadowmappcf)
2903                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2904         }
2905         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2906         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2907         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2908         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2909         switch(vid.renderpath)
2910         {
2911         case RENDERPATH_D3D9:
2912 #ifdef SUPPORTD3D
2913                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2914                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2915                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2916                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2917                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2918                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2919                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2920                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2921                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2922                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2923                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2924
2925                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2926                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2927                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2928                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2929                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2930                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2931 #endif
2932                 break;
2933         case RENDERPATH_D3D10:
2934                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2935                 break;
2936         case RENDERPATH_D3D11:
2937                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2938                 break;
2939         case RENDERPATH_GL20:
2940         case RENDERPATH_GLES2:
2941                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2942                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2943                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2944                 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);
2945                 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);
2946                 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);
2947                 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]);
2948                 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]);
2949                 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));
2950                 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]);
2951                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2952
2953                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2954                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2955                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2956                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2957                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2958                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2959                 break;
2960         case RENDERPATH_GL13:
2961         case RENDERPATH_GL11:
2962                 break;
2963         case RENDERPATH_SOFT:
2964                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2965                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2966                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2967                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2968                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2969                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2970                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2971                 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]);
2972                 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));
2973                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2974                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2975
2976                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2977                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2978                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2979                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2980                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2981                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2982                 break;
2983         }
2984 }
2985
2986 #define SKINFRAME_HASH 1024
2987
2988 typedef struct
2989 {
2990         int loadsequence; // incremented each level change
2991         memexpandablearray_t array;
2992         skinframe_t *hash[SKINFRAME_HASH];
2993 }
2994 r_skinframe_t;
2995 r_skinframe_t r_skinframe;
2996
2997 void R_SkinFrame_PrepareForPurge(void)
2998 {
2999         r_skinframe.loadsequence++;
3000         // wrap it without hitting zero
3001         if (r_skinframe.loadsequence >= 200)
3002                 r_skinframe.loadsequence = 1;
3003 }
3004
3005 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3006 {
3007         if (!skinframe)
3008                 return;
3009         // mark the skinframe as used for the purging code
3010         skinframe->loadsequence = r_skinframe.loadsequence;
3011 }
3012
3013 void R_SkinFrame_Purge(void)
3014 {
3015         int i;
3016         skinframe_t *s;
3017         for (i = 0;i < SKINFRAME_HASH;i++)
3018         {
3019                 for (s = r_skinframe.hash[i];s;s = s->next)
3020                 {
3021                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3022                         {
3023                                 if (s->merged == s->base)
3024                                         s->merged = NULL;
3025                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3026                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3027                                 R_PurgeTexture(s->merged);s->merged = NULL;
3028                                 R_PurgeTexture(s->base  );s->base   = NULL;
3029                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3030                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3031                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3032                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3033                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3034                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3035                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3036                                 s->loadsequence = 0;
3037                         }
3038                 }
3039         }
3040 }
3041
3042 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3043         skinframe_t *item;
3044         char basename[MAX_QPATH];
3045
3046         Image_StripImageExtension(name, basename, sizeof(basename));
3047
3048         if( last == NULL ) {
3049                 int hashindex;
3050                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3051                 item = r_skinframe.hash[hashindex];
3052         } else {
3053                 item = last->next;
3054         }
3055
3056         // linearly search through the hash bucket
3057         for( ; item ; item = item->next ) {
3058                 if( !strcmp( item->basename, basename ) ) {
3059                         return item;
3060                 }
3061         }
3062         return NULL;
3063 }
3064
3065 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3066 {
3067         skinframe_t *item;
3068         int hashindex;
3069         char basename[MAX_QPATH];
3070
3071         Image_StripImageExtension(name, basename, sizeof(basename));
3072
3073         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3074         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3075                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3076                         break;
3077
3078         if (!item) {
3079                 rtexture_t *dyntexture;
3080                 // check whether its a dynamic texture
3081                 dyntexture = CL_GetDynTexture( basename );
3082                 if (!add && !dyntexture)
3083                         return NULL;
3084                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3085                 memset(item, 0, sizeof(*item));
3086                 strlcpy(item->basename, basename, sizeof(item->basename));
3087                 item->base = dyntexture; // either NULL or dyntexture handle
3088                 item->textureflags = textureflags;
3089                 item->comparewidth = comparewidth;
3090                 item->compareheight = compareheight;
3091                 item->comparecrc = comparecrc;
3092                 item->next = r_skinframe.hash[hashindex];
3093                 r_skinframe.hash[hashindex] = item;
3094         }
3095         else if( item->base == NULL )
3096         {
3097                 rtexture_t *dyntexture;
3098                 // check whether its a dynamic texture
3099                 // 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]
3100                 dyntexture = CL_GetDynTexture( basename );
3101                 item->base = dyntexture; // either NULL or dyntexture handle
3102         }
3103
3104         R_SkinFrame_MarkUsed(item);
3105         return item;
3106 }
3107
3108 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3109         { \
3110                 unsigned long long avgcolor[5], wsum; \
3111                 int pix, comp, w; \
3112                 avgcolor[0] = 0; \
3113                 avgcolor[1] = 0; \
3114                 avgcolor[2] = 0; \
3115                 avgcolor[3] = 0; \
3116                 avgcolor[4] = 0; \
3117                 wsum = 0; \
3118                 for(pix = 0; pix < cnt; ++pix) \
3119                 { \
3120                         w = 0; \
3121                         for(comp = 0; comp < 3; ++comp) \
3122                                 w += getpixel; \
3123                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3124                         { \
3125                                 ++wsum; \
3126                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3127                                 w = getpixel; \
3128                                 for(comp = 0; comp < 3; ++comp) \
3129                                         avgcolor[comp] += getpixel * w; \
3130                                 avgcolor[3] += w; \
3131                         } \
3132                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3133                         avgcolor[4] += getpixel; \
3134                 } \
3135                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3136                         avgcolor[3] = 1; \
3137                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3138                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3139                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3140                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3141         }
3142
3143 extern cvar_t gl_picmip;
3144 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3145 {
3146         int j;
3147         unsigned char *pixels;
3148         unsigned char *bumppixels;
3149         unsigned char *basepixels = NULL;
3150         int basepixels_width = 0;
3151         int basepixels_height = 0;
3152         skinframe_t *skinframe;
3153         rtexture_t *ddsbase = NULL;
3154         qboolean ddshasalpha = false;
3155         float ddsavgcolor[4];
3156         char basename[MAX_QPATH];
3157         int miplevel = R_PicmipForFlags(textureflags);
3158         int savemiplevel = miplevel;
3159         int mymiplevel;
3160
3161         if (cls.state == ca_dedicated)
3162                 return NULL;
3163
3164         // return an existing skinframe if already loaded
3165         // if loading of the first image fails, don't make a new skinframe as it
3166         // would cause all future lookups of this to be missing
3167         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3168         if (skinframe && skinframe->base)
3169                 return skinframe;
3170
3171         Image_StripImageExtension(name, basename, sizeof(basename));
3172
3173         // check for DDS texture file first
3174         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3175         {
3176                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3177                 if (basepixels == NULL)
3178                         return NULL;
3179         }
3180
3181         // FIXME handle miplevel
3182
3183         if (developer_loading.integer)
3184                 Con_Printf("loading skin \"%s\"\n", name);
3185
3186         // we've got some pixels to store, so really allocate this new texture now
3187         if (!skinframe)
3188                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3189         skinframe->stain = NULL;
3190         skinframe->merged = NULL;
3191         skinframe->base = NULL;
3192         skinframe->pants = NULL;
3193         skinframe->shirt = NULL;
3194         skinframe->nmap = NULL;
3195         skinframe->gloss = NULL;
3196         skinframe->glow = NULL;
3197         skinframe->fog = NULL;
3198         skinframe->reflect = NULL;
3199         skinframe->hasalpha = false;
3200
3201         if (ddsbase)
3202         {
3203                 skinframe->base = ddsbase;
3204                 skinframe->hasalpha = ddshasalpha;
3205                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3206                 if (r_loadfog && skinframe->hasalpha)
3207                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3208                 //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]);
3209         }
3210         else
3211         {
3212                 basepixels_width = image_width;
3213                 basepixels_height = image_height;
3214                 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);
3215                 if (textureflags & TEXF_ALPHA)
3216                 {
3217                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3218                         {
3219                                 if (basepixels[j] < 255)
3220                                 {
3221                                         skinframe->hasalpha = true;
3222                                         break;
3223                                 }
3224                         }
3225                         if (r_loadfog && skinframe->hasalpha)
3226                         {
3227                                 // has transparent pixels
3228                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3229                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3230                                 {
3231                                         pixels[j+0] = 255;
3232                                         pixels[j+1] = 255;
3233                                         pixels[j+2] = 255;
3234                                         pixels[j+3] = basepixels[j+3];
3235                                 }
3236                                 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);
3237                                 Mem_Free(pixels);
3238                         }
3239                 }
3240                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3241                 //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]);
3242                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3243                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3244                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3245                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3246         }
3247
3248         if (r_loaddds)
3249         {
3250                 mymiplevel = savemiplevel;
3251                 if (r_loadnormalmap)
3252                         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);
3253                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3254                 if (r_loadgloss)
3255                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3256                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3257                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3258                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3259         }
3260
3261         // _norm is the name used by tenebrae and has been adopted as standard
3262         if (r_loadnormalmap && skinframe->nmap == NULL)
3263         {
3264                 mymiplevel = savemiplevel;
3265                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3266                 {
3267                         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);
3268                         Mem_Free(pixels);
3269                         pixels = NULL;
3270                 }
3271                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3272                 {
3273                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3274                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3275                         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);
3276                         Mem_Free(pixels);
3277                         Mem_Free(bumppixels);
3278                 }
3279                 else if (r_shadow_bumpscale_basetexture.value > 0)
3280                 {
3281                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3282                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3283                         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);
3284                         Mem_Free(pixels);
3285                 }
3286                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3287                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3288         }
3289
3290         // _luma is supported only for tenebrae compatibility
3291         // _glow is the preferred name
3292         mymiplevel = savemiplevel;
3293         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))))
3294         {
3295                 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);
3296                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3297                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3298                 Mem_Free(pixels);pixels = NULL;
3299         }
3300
3301         mymiplevel = savemiplevel;
3302         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3303         {
3304                 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);
3305                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3306                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3307                 Mem_Free(pixels);
3308                 pixels = NULL;
3309         }
3310
3311         mymiplevel = savemiplevel;
3312         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3313         {
3314                 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);
3315                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3316                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3317                 Mem_Free(pixels);
3318                 pixels = NULL;
3319         }
3320
3321         mymiplevel = savemiplevel;
3322         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3323         {
3324                 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);
3325                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3326                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3327                 Mem_Free(pixels);
3328                 pixels = NULL;
3329         }
3330
3331         mymiplevel = savemiplevel;
3332         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3333         {
3334                 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);
3335                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3336                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3337                 Mem_Free(pixels);
3338                 pixels = NULL;
3339         }
3340
3341         if (basepixels)
3342                 Mem_Free(basepixels);
3343
3344         return skinframe;
3345 }
3346
3347 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3348 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3349 {
3350         int i;
3351         unsigned char *temp1, *temp2;
3352         skinframe_t *skinframe;
3353
3354         if (cls.state == ca_dedicated)
3355                 return NULL;
3356
3357         // if already loaded just return it, otherwise make a new skinframe
3358         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3359         if (skinframe && skinframe->base)
3360                 return skinframe;
3361
3362         skinframe->stain = NULL;
3363         skinframe->merged = NULL;
3364         skinframe->base = NULL;
3365         skinframe->pants = NULL;
3366         skinframe->shirt = NULL;
3367         skinframe->nmap = NULL;
3368         skinframe->gloss = NULL;
3369         skinframe->glow = NULL;
3370         skinframe->fog = NULL;
3371         skinframe->reflect = NULL;
3372         skinframe->hasalpha = false;
3373
3374         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3375         if (!skindata)
3376                 return NULL;
3377
3378         if (developer_loading.integer)
3379                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3380
3381         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3382         {
3383                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3384                 temp2 = temp1 + width * height * 4;
3385                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3386                 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);
3387                 Mem_Free(temp1);
3388         }
3389         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3390         if (textureflags & TEXF_ALPHA)
3391         {
3392                 for (i = 3;i < width * height * 4;i += 4)
3393                 {
3394                         if (skindata[i] < 255)
3395                         {
3396                                 skinframe->hasalpha = true;
3397                                 break;
3398                         }
3399                 }
3400                 if (r_loadfog && skinframe->hasalpha)
3401                 {
3402                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3403                         memcpy(fogpixels, skindata, width * height * 4);
3404                         for (i = 0;i < width * height * 4;i += 4)
3405                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3406                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3407                         Mem_Free(fogpixels);
3408                 }
3409         }
3410
3411         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3412         //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]);
3413
3414         return skinframe;
3415 }
3416
3417 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3418 {
3419         int i;
3420         int featuresmask;
3421         skinframe_t *skinframe;
3422
3423         if (cls.state == ca_dedicated)
3424                 return NULL;
3425
3426         // if already loaded just return it, otherwise make a new skinframe
3427         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3428         if (skinframe && skinframe->base)
3429                 return skinframe;
3430
3431         skinframe->stain = NULL;
3432         skinframe->merged = NULL;
3433         skinframe->base = NULL;
3434         skinframe->pants = NULL;
3435         skinframe->shirt = NULL;
3436         skinframe->nmap = NULL;
3437         skinframe->gloss = NULL;
3438         skinframe->glow = NULL;
3439         skinframe->fog = NULL;
3440         skinframe->reflect = NULL;
3441         skinframe->hasalpha = false;
3442
3443         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3444         if (!skindata)
3445                 return NULL;
3446
3447         if (developer_loading.integer)
3448                 Con_Printf("loading quake skin \"%s\"\n", name);
3449
3450         // 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)
3451         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3452         memcpy(skinframe->qpixels, skindata, width*height);
3453         skinframe->qwidth = width;
3454         skinframe->qheight = height;
3455
3456         featuresmask = 0;
3457         for (i = 0;i < width * height;i++)
3458                 featuresmask |= palette_featureflags[skindata[i]];
3459
3460         skinframe->hasalpha = false;
3461         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3462         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3463         skinframe->qgeneratemerged = true;
3464         skinframe->qgeneratebase = skinframe->qhascolormapping;
3465         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3466
3467         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3468         //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]);
3469
3470         return skinframe;
3471 }
3472
3473 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3474 {
3475         int width;
3476         int height;
3477         unsigned char *skindata;
3478
3479         if (!skinframe->qpixels)
3480                 return;
3481
3482         if (!skinframe->qhascolormapping)
3483                 colormapped = false;
3484
3485         if (colormapped)
3486         {
3487                 if (!skinframe->qgeneratebase)
3488                         return;
3489         }
3490         else
3491         {
3492                 if (!skinframe->qgeneratemerged)
3493                         return;
3494         }
3495
3496         width = skinframe->qwidth;
3497         height = skinframe->qheight;
3498         skindata = skinframe->qpixels;
3499
3500         if (skinframe->qgeneratenmap)
3501         {
3502                 unsigned char *temp1, *temp2;
3503                 skinframe->qgeneratenmap = false;
3504                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3505                 temp2 = temp1 + width * height * 4;
3506                 // use either a custom palette or the quake palette
3507                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3508                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3509                 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);
3510                 Mem_Free(temp1);
3511         }
3512
3513         if (skinframe->qgenerateglow)
3514         {
3515                 skinframe->qgenerateglow = false;
3516                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3517         }
3518
3519         if (colormapped)
3520         {
3521                 skinframe->qgeneratebase = false;
3522                 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);
3523                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3524                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3525         }
3526         else
3527         {
3528                 skinframe->qgeneratemerged = false;
3529                 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);
3530         }
3531
3532         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3533         {
3534                 Mem_Free(skinframe->qpixels);
3535                 skinframe->qpixels = NULL;
3536         }
3537 }
3538
3539 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)
3540 {
3541         int i;
3542         skinframe_t *skinframe;
3543
3544         if (cls.state == ca_dedicated)
3545                 return NULL;
3546
3547         // if already loaded just return it, otherwise make a new skinframe
3548         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3549         if (skinframe && skinframe->base)
3550                 return skinframe;
3551
3552         skinframe->stain = NULL;
3553         skinframe->merged = NULL;
3554         skinframe->base = NULL;
3555         skinframe->pants = NULL;
3556         skinframe->shirt = NULL;
3557         skinframe->nmap = NULL;
3558         skinframe->gloss = NULL;
3559         skinframe->glow = NULL;
3560         skinframe->fog = NULL;
3561         skinframe->reflect = NULL;
3562         skinframe->hasalpha = false;
3563
3564         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3565         if (!skindata)
3566                 return NULL;
3567
3568         if (developer_loading.integer)
3569                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3570
3571         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3572         if (textureflags & TEXF_ALPHA)
3573         {
3574                 for (i = 0;i < width * height;i++)
3575                 {
3576                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3577                         {
3578                                 skinframe->hasalpha = true;
3579                                 break;
3580                         }
3581                 }
3582                 if (r_loadfog && skinframe->hasalpha)
3583                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3584         }
3585
3586         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3587         //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]);
3588
3589         return skinframe;
3590 }
3591
3592 skinframe_t *R_SkinFrame_LoadMissing(void)
3593 {
3594         skinframe_t *skinframe;
3595
3596         if (cls.state == ca_dedicated)
3597                 return NULL;
3598
3599         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3600         skinframe->stain = NULL;
3601         skinframe->merged = NULL;
3602         skinframe->base = NULL;
3603         skinframe->pants = NULL;
3604         skinframe->shirt = NULL;
3605         skinframe->nmap = NULL;
3606         skinframe->gloss = NULL;
3607         skinframe->glow = NULL;
3608         skinframe->fog = NULL;
3609         skinframe->reflect = NULL;
3610         skinframe->hasalpha = false;
3611
3612         skinframe->avgcolor[0] = rand() / RAND_MAX;
3613         skinframe->avgcolor[1] = rand() / RAND_MAX;
3614         skinframe->avgcolor[2] = rand() / RAND_MAX;
3615         skinframe->avgcolor[3] = 1;
3616
3617         return skinframe;
3618 }
3619
3620 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3621 typedef struct suffixinfo_s
3622 {
3623         const char *suffix;
3624         qboolean flipx, flipy, flipdiagonal;
3625 }
3626 suffixinfo_t;
3627 static suffixinfo_t suffix[3][6] =
3628 {
3629         {
3630                 {"px",   false, false, false},
3631                 {"nx",   false, false, false},
3632                 {"py",   false, false, false},
3633                 {"ny",   false, false, false},
3634                 {"pz",   false, false, false},
3635                 {"nz",   false, false, false}
3636         },
3637         {
3638                 {"posx", false, false, false},
3639                 {"negx", false, false, false},
3640                 {"posy", false, false, false},
3641                 {"negy", false, false, false},
3642                 {"posz", false, false, false},
3643                 {"negz", false, false, false}
3644         },
3645         {
3646                 {"rt",    true, false,  true},
3647                 {"lf",   false,  true,  true},
3648                 {"ft",    true,  true, false},
3649                 {"bk",   false, false, false},
3650                 {"up",    true, false,  true},
3651                 {"dn",    true, false,  true}
3652         }
3653 };
3654
3655 static int componentorder[4] = {0, 1, 2, 3};
3656
3657 rtexture_t *R_LoadCubemap(const char *basename)
3658 {
3659         int i, j, cubemapsize;
3660         unsigned char *cubemappixels, *image_buffer;
3661         rtexture_t *cubemaptexture;
3662         char name[256];
3663         // must start 0 so the first loadimagepixels has no requested width/height
3664         cubemapsize = 0;
3665         cubemappixels = NULL;
3666         cubemaptexture = NULL;
3667         // keep trying different suffix groups (posx, px, rt) until one loads
3668         for (j = 0;j < 3 && !cubemappixels;j++)
3669         {
3670                 // load the 6 images in the suffix group
3671                 for (i = 0;i < 6;i++)
3672                 {
3673                         // generate an image name based on the base and and suffix
3674                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3675                         // load it
3676                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3677                         {
3678                                 // an image loaded, make sure width and height are equal
3679                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3680                                 {
3681                                         // if this is the first image to load successfully, allocate the cubemap memory
3682                                         if (!cubemappixels && image_width >= 1)
3683                                         {
3684                                                 cubemapsize = image_width;
3685                                                 // note this clears to black, so unavailable sides are black
3686                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3687                                         }
3688                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3689                                         if (cubemappixels)
3690                                                 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);
3691                                 }
3692                                 else
3693                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3694                                 // free the image
3695                                 Mem_Free(image_buffer);
3696                         }
3697                 }
3698         }
3699         // if a cubemap loaded, upload it
3700         if (cubemappixels)
3701         {
3702                 if (developer_loading.integer)
3703                         Con_Printf("loading cubemap \"%s\"\n", basename);
3704
3705                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3706                 Mem_Free(cubemappixels);
3707         }
3708         else
3709         {
3710                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3711                 if (developer_loading.integer)
3712                 {
3713                         Con_Printf("(tried tried images ");
3714                         for (j = 0;j < 3;j++)
3715                                 for (i = 0;i < 6;i++)
3716                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3717                         Con_Print(" and was unable to find any of them).\n");
3718                 }
3719         }
3720         return cubemaptexture;
3721 }
3722
3723 rtexture_t *R_GetCubemap(const char *basename)
3724 {
3725         int i;
3726         for (i = 0;i < r_texture_numcubemaps;i++)
3727                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3728                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3729         if (i >= MAX_CUBEMAPS)
3730                 return r_texture_whitecube;
3731         r_texture_numcubemaps++;
3732         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3733         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3734         return r_texture_cubemaps[i].texture;
3735 }
3736
3737 void R_FreeCubemaps(void)
3738 {
3739         int i;
3740         for (i = 0;i < r_texture_numcubemaps;i++)
3741         {
3742                 if (developer_loading.integer)
3743                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3744                 if (r_texture_cubemaps[i].texture)
3745                         R_FreeTexture(r_texture_cubemaps[i].texture);
3746         }
3747         r_texture_numcubemaps = 0;
3748 }
3749
3750 void R_Main_FreeViewCache(void)
3751 {
3752         if (r_refdef.viewcache.entityvisible)
3753                 Mem_Free(r_refdef.viewcache.entityvisible);
3754         if (r_refdef.viewcache.world_pvsbits)
3755                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3756         if (r_refdef.viewcache.world_leafvisible)
3757                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3758         if (r_refdef.viewcache.world_surfacevisible)
3759                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3760         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3761 }
3762
3763 void R_Main_ResizeViewCache(void)
3764 {
3765         int numentities = r_refdef.scene.numentities;
3766         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3767         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3768         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3769         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3770         if (r_refdef.viewcache.maxentities < numentities)
3771         {
3772                 r_refdef.viewcache.maxentities = numentities;
3773                 if (r_refdef.viewcache.entityvisible)
3774                         Mem_Free(r_refdef.viewcache.entityvisible);
3775                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3776         }
3777         if (r_refdef.viewcache.world_numclusters != numclusters)
3778         {
3779                 r_refdef.viewcache.world_numclusters = numclusters;
3780                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3781                 if (r_refdef.viewcache.world_pvsbits)
3782                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3783                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3784         }
3785         if (r_refdef.viewcache.world_numleafs != numleafs)
3786         {
3787                 r_refdef.viewcache.world_numleafs = numleafs;
3788                 if (r_refdef.viewcache.world_leafvisible)
3789                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3790                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3791         }
3792         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3793         {
3794                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3795                 if (r_refdef.viewcache.world_surfacevisible)
3796                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3797                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3798         }
3799 }
3800
3801 extern rtexture_t *loadingscreentexture;
3802 void gl_main_start(void)
3803 {
3804         loadingscreentexture = NULL;
3805         r_texture_blanknormalmap = NULL;
3806         r_texture_white = NULL;
3807         r_texture_grey128 = NULL;
3808         r_texture_black = NULL;
3809         r_texture_whitecube = NULL;
3810         r_texture_normalizationcube = NULL;
3811         r_texture_fogattenuation = NULL;
3812         r_texture_fogheighttexture = NULL;
3813         r_texture_gammaramps = NULL;
3814         r_texture_numcubemaps = 0;
3815
3816         r_loaddds = r_texture_dds_load.integer != 0;
3817         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3818
3819         switch(vid.renderpath)
3820         {
3821         case RENDERPATH_GL20:
3822         case RENDERPATH_D3D9:
3823         case RENDERPATH_D3D10:
3824         case RENDERPATH_D3D11:
3825         case RENDERPATH_SOFT:
3826                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3827                 Cvar_SetValueQuick(&gl_combine, 1);
3828                 Cvar_SetValueQuick(&r_glsl, 1);
3829                 r_loadnormalmap = true;
3830                 r_loadgloss = true;
3831                 r_loadfog = false;
3832                 break;
3833         case RENDERPATH_GL13:
3834                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3835                 Cvar_SetValueQuick(&gl_combine, 1);
3836                 Cvar_SetValueQuick(&r_glsl, 0);
3837                 r_loadnormalmap = false;
3838                 r_loadgloss = false;
3839                 r_loadfog = true;
3840                 break;
3841         case RENDERPATH_GL11:
3842                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3843                 Cvar_SetValueQuick(&gl_combine, 0);
3844                 Cvar_SetValueQuick(&r_glsl, 0);
3845                 r_loadnormalmap = false;
3846                 r_loadgloss = false;
3847                 r_loadfog = true;
3848                 break;
3849         case RENDERPATH_GLES2:
3850                 Cvar_SetValueQuick(&r_textureunits, 1);
3851                 Cvar_SetValueQuick(&gl_combine, 1);
3852                 Cvar_SetValueQuick(&r_glsl, 1);
3853                 r_loadnormalmap = true;
3854                 r_loadgloss = false;
3855                 r_loadfog = false;
3856                 break;
3857         }
3858
3859         R_AnimCache_Free();
3860         R_FrameData_Reset();
3861
3862         r_numqueries = 0;
3863         r_maxqueries = 0;
3864         memset(r_queries, 0, sizeof(r_queries));
3865
3866         r_qwskincache = NULL;
3867         r_qwskincache_size = 0;
3868
3869         // due to caching of texture_t references, the collision cache must be reset
3870         Collision_Cache_Reset(true);
3871
3872         // set up r_skinframe loading system for textures
3873         memset(&r_skinframe, 0, sizeof(r_skinframe));
3874         r_skinframe.loadsequence = 1;
3875         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3876
3877         r_main_texturepool = R_AllocTexturePool();
3878         R_BuildBlankTextures();
3879         R_BuildNoTexture();
3880         if (vid.support.arb_texture_cube_map)
3881         {
3882                 R_BuildWhiteCube();
3883                 R_BuildNormalizationCube();
3884         }
3885         r_texture_fogattenuation = NULL;
3886         r_texture_fogheighttexture = NULL;
3887         r_texture_gammaramps = NULL;
3888         //r_texture_fogintensity = NULL;
3889         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3890         memset(&r_waterstate, 0, sizeof(r_waterstate));
3891         r_glsl_permutation = NULL;
3892         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3893         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3894         glslshaderstring = NULL;
3895 #ifdef SUPPORTD3D
3896         r_hlsl_permutation = NULL;
3897         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3898         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3899 #endif
3900         hlslshaderstring = NULL;
3901         memset(&r_svbsp, 0, sizeof (r_svbsp));
3902
3903         r_refdef.fogmasktable_density = 0;
3904 }
3905
3906 void gl_main_shutdown(void)
3907 {
3908         R_AnimCache_Free();
3909         R_FrameData_Reset();
3910
3911         R_Main_FreeViewCache();
3912
3913         switch(vid.renderpath)
3914         {
3915         case RENDERPATH_GL11:
3916         case RENDERPATH_GL13:
3917         case RENDERPATH_GL20:
3918         case RENDERPATH_GLES2:
3919                 if (r_maxqueries)
3920                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3921                 break;
3922         case RENDERPATH_D3D9:
3923                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3924                 break;
3925         case RENDERPATH_D3D10:
3926                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3927                 break;
3928         case RENDERPATH_D3D11:
3929                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3930                 break;
3931         case RENDERPATH_SOFT:
3932                 break;
3933         }
3934
3935         r_numqueries = 0;
3936         r_maxqueries = 0;
3937         memset(r_queries, 0, sizeof(r_queries));
3938
3939         r_qwskincache = NULL;
3940         r_qwskincache_size = 0;
3941
3942         // clear out the r_skinframe state
3943         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3944         memset(&r_skinframe, 0, sizeof(r_skinframe));
3945
3946         if (r_svbsp.nodes)
3947                 Mem_Free(r_svbsp.nodes);
3948         memset(&r_svbsp, 0, sizeof (r_svbsp));
3949         R_FreeTexturePool(&r_main_texturepool);
3950         loadingscreentexture = NULL;
3951         r_texture_blanknormalmap = NULL;
3952         r_texture_white = NULL;
3953         r_texture_grey128 = NULL;
3954         r_texture_black = NULL;
3955         r_texture_whitecube = NULL;
3956         r_texture_normalizationcube = NULL;
3957         r_texture_fogattenuation = NULL;
3958         r_texture_fogheighttexture = NULL;
3959         r_texture_gammaramps = NULL;
3960         r_texture_numcubemaps = 0;
3961         //r_texture_fogintensity = NULL;
3962         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3963         memset(&r_waterstate, 0, sizeof(r_waterstate));
3964         R_GLSL_Restart_f();
3965
3966         r_glsl_permutation = NULL;
3967         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3968         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3969         glslshaderstring = NULL;
3970 #ifdef SUPPORTD3D
3971         r_hlsl_permutation = NULL;
3972         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3973         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3974 #endif
3975         hlslshaderstring = NULL;
3976 }
3977
3978 extern void CL_ParseEntityLump(char *entitystring);
3979 void gl_main_newmap(void)
3980 {
3981         // FIXME: move this code to client
3982         char *entities, entname[MAX_QPATH];
3983         if (r_qwskincache)
3984                 Mem_Free(r_qwskincache);
3985         r_qwskincache = NULL;
3986         r_qwskincache_size = 0;
3987         if (cl.worldmodel)
3988         {
3989                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3990                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3991                 {
3992                         CL_ParseEntityLump(entities);
3993                         Mem_Free(entities);
3994                         return;
3995                 }
3996                 if (cl.worldmodel->brush.entities)
3997                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3998         }
3999         R_Main_FreeViewCache();
4000
4001         R_FrameData_Reset();
4002 }
4003
4004 void GL_Main_Init(void)
4005 {
4006         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4007
4008         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4009         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4010         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4011         if (gamemode == GAME_NEHAHRA)
4012         {
4013                 Cvar_RegisterVariable (&gl_fogenable);
4014                 Cvar_RegisterVariable (&gl_fogdensity);
4015                 Cvar_RegisterVariable (&gl_fogred);
4016                 Cvar_RegisterVariable (&gl_foggreen);
4017                 Cvar_RegisterVariable (&gl_fogblue);
4018                 Cvar_RegisterVariable (&gl_fogstart);
4019                 Cvar_RegisterVariable (&gl_fogend);
4020                 Cvar_RegisterVariable (&gl_skyclip);
4021         }
4022         Cvar_RegisterVariable(&r_motionblur);
4023         Cvar_RegisterVariable(&r_motionblur_maxblur);
4024         Cvar_RegisterVariable(&r_motionblur_bmin);
4025         Cvar_RegisterVariable(&r_motionblur_vmin);
4026         Cvar_RegisterVariable(&r_motionblur_vmax);
4027         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4028         Cvar_RegisterVariable(&r_motionblur_randomize);
4029         Cvar_RegisterVariable(&r_damageblur);
4030         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4031         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4032         Cvar_RegisterVariable(&r_equalize_entities_by);
4033         Cvar_RegisterVariable(&r_equalize_entities_to);
4034         Cvar_RegisterVariable(&r_depthfirst);
4035         Cvar_RegisterVariable(&r_useinfinitefarclip);
4036         Cvar_RegisterVariable(&r_farclip_base);
4037         Cvar_RegisterVariable(&r_farclip_world);
4038         Cvar_RegisterVariable(&r_nearclip);
4039         Cvar_RegisterVariable(&r_showbboxes);
4040         Cvar_RegisterVariable(&r_showsurfaces);
4041         Cvar_RegisterVariable(&r_showtris);
4042         Cvar_RegisterVariable(&r_shownormals);
4043         Cvar_RegisterVariable(&r_showlighting);
4044         Cvar_RegisterVariable(&r_showshadowvolumes);
4045         Cvar_RegisterVariable(&r_showcollisionbrushes);
4046         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4047         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4048         Cvar_RegisterVariable(&r_showdisabledepthtest);
4049         Cvar_RegisterVariable(&r_drawportals);
4050         Cvar_RegisterVariable(&r_drawentities);
4051         Cvar_RegisterVariable(&r_draw2d);
4052         Cvar_RegisterVariable(&r_drawworld);
4053         Cvar_RegisterVariable(&r_cullentities_trace);
4054         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4055         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4056         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4057         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4058         Cvar_RegisterVariable(&r_drawviewmodel);
4059         Cvar_RegisterVariable(&r_drawexteriormodel);
4060         Cvar_RegisterVariable(&r_speeds);
4061         Cvar_RegisterVariable(&r_fullbrights);
4062         Cvar_RegisterVariable(&r_wateralpha);
4063         Cvar_RegisterVariable(&r_dynamic);
4064         Cvar_RegisterVariable(&r_fakelight);
4065         Cvar_RegisterVariable(&r_fakelight_intensity);
4066         Cvar_RegisterVariable(&r_fullbright);
4067         Cvar_RegisterVariable(&r_shadows);
4068         Cvar_RegisterVariable(&r_shadows_darken);
4069         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4070         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4071         Cvar_RegisterVariable(&r_shadows_throwdistance);
4072         Cvar_RegisterVariable(&r_shadows_throwdirection);
4073         Cvar_RegisterVariable(&r_shadows_focus);
4074         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4075         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4076         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4077         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4078         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4079         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4080         Cvar_RegisterVariable(&r_fog_exp2);
4081         Cvar_RegisterVariable(&r_drawfog);
4082         Cvar_RegisterVariable(&r_transparentdepthmasking);
4083         Cvar_RegisterVariable(&r_texture_dds_load);
4084         Cvar_RegisterVariable(&r_texture_dds_save);
4085         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4086         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4087         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4088         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4089         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4090         Cvar_RegisterVariable(&r_textureunits);
4091         Cvar_RegisterVariable(&gl_combine);
4092         Cvar_RegisterVariable(&r_glsl);
4093         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4094         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4095         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4096         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4097         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4098         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4099         Cvar_RegisterVariable(&r_glsl_postprocess);
4100         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4101         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4102         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4103         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4104         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4105         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4106         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4107         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4108
4109         Cvar_RegisterVariable(&r_water);
4110         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4111         Cvar_RegisterVariable(&r_water_clippingplanebias);
4112         Cvar_RegisterVariable(&r_water_refractdistort);
4113         Cvar_RegisterVariable(&r_water_reflectdistort);
4114         Cvar_RegisterVariable(&r_water_scissormode);
4115         Cvar_RegisterVariable(&r_lerpsprites);
4116         Cvar_RegisterVariable(&r_lerpmodels);
4117         Cvar_RegisterVariable(&r_lerplightstyles);
4118         Cvar_RegisterVariable(&r_waterscroll);
4119         Cvar_RegisterVariable(&r_bloom);
4120         Cvar_RegisterVariable(&r_bloom_colorscale);
4121         Cvar_RegisterVariable(&r_bloom_brighten);
4122         Cvar_RegisterVariable(&r_bloom_blur);
4123         Cvar_RegisterVariable(&r_bloom_resolution);
4124         Cvar_RegisterVariable(&r_bloom_colorexponent);
4125         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4126         Cvar_RegisterVariable(&r_hdr);
4127         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4128         Cvar_RegisterVariable(&r_hdr_glowintensity);
4129         Cvar_RegisterVariable(&r_hdr_range);
4130         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4131         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4132         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4133         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4134         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4135         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4136         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4137         Cvar_RegisterVariable(&developer_texturelogging);
4138         Cvar_RegisterVariable(&gl_lightmaps);
4139         Cvar_RegisterVariable(&r_test);
4140         Cvar_RegisterVariable(&r_glsl_saturation);
4141         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4142         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4143         Cvar_RegisterVariable(&r_framedatasize);
4144         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4145                 Cvar_SetValue("r_fullbrights", 0);
4146         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4147
4148         Cvar_RegisterVariable(&r_track_sprites);
4149         Cvar_RegisterVariable(&r_track_sprites_flags);
4150         Cvar_RegisterVariable(&r_track_sprites_scalew);
4151         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4152         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4153         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4154         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4155         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4156 }
4157
4158 extern void R_Textures_Init(void);
4159 extern void GL_Draw_Init(void);
4160 extern void GL_Main_Init(void);
4161 extern void R_Shadow_Init(void);
4162 extern void R_Sky_Init(void);
4163 extern void GL_Surf_Init(void);
4164 extern void R_Particles_Init(void);
4165 extern void R_Explosion_Init(void);
4166 extern void gl_backend_init(void);
4167 extern void Sbar_Init(void);
4168 extern void R_LightningBeams_Init(void);
4169 extern void Mod_RenderInit(void);
4170 extern void Font_Init(void);
4171
4172 void Render_Init(void)
4173 {
4174         gl_backend_init();
4175         R_Textures_Init();
4176         GL_Main_Init();
4177         Font_Init();
4178         GL_Draw_Init();
4179         R_Shadow_Init();
4180         R_Sky_Init();
4181         GL_Surf_Init();
4182         Sbar_Init();
4183         R_Particles_Init();
4184         R_Explosion_Init();
4185         R_LightningBeams_Init();
4186         Mod_RenderInit();
4187 }
4188
4189 /*
4190 ===============
4191 GL_Init
4192 ===============
4193 */
4194 extern char *ENGINE_EXTENSIONS;
4195 void GL_Init (void)
4196 {
4197         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4198         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4199         gl_version = (const char *)qglGetString(GL_VERSION);
4200         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4201
4202         if (!gl_extensions)
4203                 gl_extensions = "";
4204         if (!gl_platformextensions)
4205                 gl_platformextensions = "";
4206
4207         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4208         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4209         Con_Printf("GL_VERSION: %s\n", gl_version);
4210         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4211         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4212
4213         VID_CheckExtensions();
4214
4215         // LordHavoc: report supported extensions
4216         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4217
4218         // clear to black (loading plaque will be seen over this)
4219         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4220 }
4221
4222 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4223 {
4224         int i;
4225         mplane_t *p;
4226         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4227         {
4228                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4229                 if (i == 4)
4230                         continue;
4231                 p = r_refdef.view.frustum + i;
4232                 switch(p->signbits)
4233                 {
4234                 default:
4235                 case 0:
4236                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4237                                 return true;
4238                         break;
4239                 case 1:
4240                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4241                                 return true;
4242                         break;
4243                 case 2:
4244                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4245                                 return true;
4246                         break;
4247                 case 3:
4248                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4249                                 return true;
4250                         break;
4251                 case 4:
4252                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4253                                 return true;
4254                         break;
4255                 case 5:
4256                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4257                                 return true;
4258                         break;
4259                 case 6:
4260                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4261                                 return true;
4262                         break;
4263                 case 7:
4264                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4265                                 return true;
4266                         break;
4267                 }
4268         }
4269         return false;
4270 }
4271
4272 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4273 {
4274         int i;
4275         const mplane_t *p;
4276         for (i = 0;i < numplanes;i++)
4277         {
4278                 p = planes + i;
4279                 switch(p->signbits)
4280                 {
4281                 default:
4282                 case 0:
4283                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4284                                 return true;
4285                         break;
4286                 case 1:
4287                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4288                                 return true;
4289                         break;
4290                 case 2:
4291                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4292                                 return true;
4293                         break;
4294                 case 3:
4295                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4296                                 return true;
4297                         break;
4298                 case 4:
4299                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4300                                 return true;
4301                         break;
4302                 case 5:
4303                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4304                                 return true;
4305                         break;
4306                 case 6:
4307                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4308                                 return true;
4309                         break;
4310                 case 7:
4311                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4312                                 return true;
4313                         break;
4314                 }
4315         }
4316         return false;
4317 }
4318
4319 //==================================================================================
4320
4321 // LordHavoc: this stores temporary data used within the same frame
4322
4323 typedef struct r_framedata_mem_s
4324 {
4325         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4326         size_t size; // how much usable space
4327         size_t current; // how much space in use
4328         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4329         size_t wantedsize; // how much space was allocated
4330         unsigned char *data; // start of real data (16byte aligned)
4331 }
4332 r_framedata_mem_t;
4333
4334 static r_framedata_mem_t *r_framedata_mem;
4335
4336 void R_FrameData_Reset(void)
4337 {
4338         while (r_framedata_mem)
4339         {
4340                 r_framedata_mem_t *next = r_framedata_mem->purge;
4341                 Mem_Free(r_framedata_mem);
4342                 r_framedata_mem = next;
4343         }
4344 }
4345
4346 void R_FrameData_Resize(void)
4347 {
4348         size_t wantedsize;
4349         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4350         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4351         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4352         {
4353                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4354                 newmem->wantedsize = wantedsize;
4355                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4356                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4357                 newmem->current = 0;
4358                 newmem->mark = 0;
4359                 newmem->purge = r_framedata_mem;
4360                 r_framedata_mem = newmem;
4361         }
4362 }
4363
4364 void R_FrameData_NewFrame(void)
4365 {
4366         R_FrameData_Resize();
4367         if (!r_framedata_mem)
4368                 return;
4369         // if we ran out of space on the last frame, free the old memory now
4370         while (r_framedata_mem->purge)
4371         {
4372                 // repeatedly remove the second item in the list, leaving only head
4373                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4374                 Mem_Free(r_framedata_mem->purge);
4375                 r_framedata_mem->purge = next;
4376         }
4377         // reset the current mem pointer
4378         r_framedata_mem->current = 0;
4379         r_framedata_mem->mark = 0;
4380 }
4381
4382 void *R_FrameData_Alloc(size_t size)
4383 {
4384         void *data;
4385
4386         // align to 16 byte boundary - the data pointer is already aligned, so we
4387         // only need to ensure the size of every allocation is also aligned
4388         size = (size + 15) & ~15;
4389
4390         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4391         {
4392                 // emergency - we ran out of space, allocate more memory
4393                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4394                 R_FrameData_Resize();
4395         }
4396
4397         data = r_framedata_mem->data + r_framedata_mem->current;
4398         r_framedata_mem->current += size;
4399
4400         // count the usage for stats
4401         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4402         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4403
4404         return (void *)data;
4405 }
4406
4407 void *R_FrameData_Store(size_t size, void *data)
4408 {
4409         void *d = R_FrameData_Alloc(size);
4410         if (d && data)
4411                 memcpy(d, data, size);
4412         return d;
4413 }
4414
4415 void R_FrameData_SetMark(void)
4416 {
4417         if (!r_framedata_mem)
4418                 return;
4419         r_framedata_mem->mark = r_framedata_mem->current;
4420 }
4421
4422 void R_FrameData_ReturnToMark(void)
4423 {
4424         if (!r_framedata_mem)
4425                 return;
4426         r_framedata_mem->current = r_framedata_mem->mark;
4427 }
4428
4429 //==================================================================================
4430
4431 // LordHavoc: animcache originally written by Echon, rewritten since then
4432
4433 /**
4434  * Animation cache prevents re-generating mesh data for an animated model
4435  * multiple times in one frame for lighting, shadowing, reflections, etc.
4436  */
4437
4438 void R_AnimCache_Free(void)
4439 {
4440 }
4441
4442 void R_AnimCache_ClearCache(void)
4443 {
4444         int i;
4445         entity_render_t *ent;
4446
4447         for (i = 0;i < r_refdef.scene.numentities;i++)
4448         {
4449                 ent = r_refdef.scene.entities[i];
4450                 ent->animcache_vertex3f = NULL;
4451                 ent->animcache_normal3f = NULL;
4452                 ent->animcache_svector3f = NULL;
4453                 ent->animcache_tvector3f = NULL;
4454                 ent->animcache_vertexmesh = NULL;
4455                 ent->animcache_vertex3fbuffer = NULL;
4456                 ent->animcache_vertexmeshbuffer = NULL;
4457         }
4458 }
4459
4460 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4461 {
4462         int i;
4463
4464         // check if we need the meshbuffers
4465         if (!vid.useinterleavedarrays)
4466                 return;
4467
4468         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4469                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4470         // TODO: upload vertex3f buffer?
4471         if (ent->animcache_vertexmesh)
4472         {
4473                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4474                 for (i = 0;i < numvertices;i++)
4475                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4476                 if (ent->animcache_svector3f)
4477                         for (i = 0;i < numvertices;i++)
4478                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4479                 if (ent->animcache_tvector3f)
4480                         for (i = 0;i < numvertices;i++)
4481                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4482                 if (ent->animcache_normal3f)
4483                         for (i = 0;i < numvertices;i++)
4484                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4485                 // TODO: upload vertexmeshbuffer?
4486         }
4487 }
4488
4489 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4490 {
4491         dp_model_t *model = ent->model;
4492         int numvertices;
4493         // see if it's already cached this frame
4494         if (ent->animcache_vertex3f)
4495         {
4496                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4497                 if (wantnormals || wanttangents)
4498                 {
4499                         if (ent->animcache_normal3f)
4500                                 wantnormals = false;
4501                         if (ent->animcache_svector3f)
4502                                 wanttangents = false;
4503                         if (wantnormals || wanttangents)
4504                         {
4505                                 numvertices = model->surfmesh.num_vertices;
4506                                 if (wantnormals)
4507                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4508                                 if (wanttangents)
4509                                 {
4510                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4511                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4512                                 }
4513                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4514                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4515                         }
4516                 }
4517         }
4518         else
4519         {
4520                 // see if this ent is worth caching
4521                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4522                         return false;
4523                 // get some memory for this entity and generate mesh data
4524                 numvertices = model->surfmesh.num_vertices;
4525                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4526                 if (wantnormals)
4527                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4528                 if (wanttangents)
4529                 {
4530                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4531                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4532                 }
4533                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4534                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4535         }
4536         return true;
4537 }
4538
4539 void R_AnimCache_CacheVisibleEntities(void)
4540 {
4541         int i;
4542         qboolean wantnormals = true;
4543         qboolean wanttangents = !r_showsurfaces.integer;
4544
4545         switch(vid.renderpath)
4546         {
4547         case RENDERPATH_GL20:
4548         case RENDERPATH_D3D9:
4549         case RENDERPATH_D3D10:
4550         case RENDERPATH_D3D11:
4551         case RENDERPATH_GLES2:
4552                 break;
4553         case RENDERPATH_GL13:
4554         case RENDERPATH_GL11:
4555                 wanttangents = false;
4556                 break;
4557         case RENDERPATH_SOFT:
4558                 break;
4559         }
4560
4561         if (r_shownormals.integer)
4562                 wanttangents = wantnormals = true;
4563
4564         // TODO: thread this
4565         // NOTE: R_PrepareRTLights() also caches entities
4566
4567         for (i = 0;i < r_refdef.scene.numentities;i++)
4568                 if (r_refdef.viewcache.entityvisible[i])
4569                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4570 }
4571
4572 //==================================================================================
4573
4574 static void R_View_UpdateEntityLighting (void)
4575 {
4576         int i;
4577         entity_render_t *ent;
4578         vec3_t tempdiffusenormal, avg;
4579         vec_t f, fa, fd, fdd;
4580         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4581
4582         for (i = 0;i < r_refdef.scene.numentities;i++)
4583         {
4584                 ent = r_refdef.scene.entities[i];
4585
4586                 // skip unseen models
4587                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4588                         continue;
4589
4590                 // skip bsp models
4591                 if (ent->model && ent->model->brush.num_leafs)
4592                 {
4593                         // TODO: use modellight for r_ambient settings on world?
4594                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4595                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4596                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4597                         continue;
4598                 }
4599
4600                 // fetch the lighting from the worldmodel data
4601                 VectorClear(ent->modellight_ambient);
4602                 VectorClear(ent->modellight_diffuse);
4603                 VectorClear(tempdiffusenormal);
4604                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4605                 {
4606                         vec3_t org;
4607                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4608
4609                         // complete lightning for lit sprites
4610                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4611                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4612                         {
4613                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4614                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4615                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4616                         }
4617                         else
4618                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4619
4620                         if(ent->flags & RENDER_EQUALIZE)
4621                         {
4622                                 // first fix up ambient lighting...
4623                                 if(r_equalize_entities_minambient.value > 0)
4624                                 {
4625                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4626                                         if(fd > 0)
4627                                         {
4628                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4629                                                 if(fa < r_equalize_entities_minambient.value * fd)
4630                                                 {
4631                                                         // solve:
4632                                                         //   fa'/fd' = minambient
4633                                                         //   fa'+0.25*fd' = fa+0.25*fd
4634                                                         //   ...
4635                                                         //   fa' = fd' * minambient
4636                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4637                                                         //   ...
4638                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4639                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4640                                                         //   ...
4641                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4642                                                         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
4643                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4644                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4645                                                 }
4646                                         }
4647                                 }
4648
4649                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4650                                 {
4651                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4652                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4653                                         f = fa + 0.25 * fd;
4654                                         if(f > 0)
4655                                         {
4656                                                 // adjust brightness and saturation to target
4657                                                 avg[0] = avg[1] = avg[2] = fa / f;
4658                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4659                                                 avg[0] = avg[1] = avg[2] = fd / f;
4660                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4661                                         }
4662                                 }
4663                         }
4664                 }
4665                 else // highly rare
4666                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4667
4668                 // move the light direction into modelspace coordinates for lighting code
4669                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4670                 if(VectorLength2(ent->modellight_lightdir) == 0)
4671                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4672                 VectorNormalize(ent->modellight_lightdir);
4673         }
4674 }
4675
4676 #define MAX_LINEOFSIGHTTRACES 64
4677
4678 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4679 {
4680         int i;
4681         vec3_t boxmins, boxmaxs;
4682         vec3_t start;
4683         vec3_t end;
4684         dp_model_t *model = r_refdef.scene.worldmodel;
4685
4686         if (!model || !model->brush.TraceLineOfSight)
4687                 return true;
4688
4689         // expand the box a little
4690         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4691         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4692         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4693         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4694         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4695         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4696
4697         // return true if eye is inside enlarged box
4698         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4699                 return true;
4700
4701         // try center
4702         VectorCopy(eye, start);
4703         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4704         if (model->brush.TraceLineOfSight(model, start, end))
4705                 return true;
4706
4707         // try various random positions
4708         for (i = 0;i < numsamples;i++)
4709         {
4710                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4711                 if (model->brush.TraceLineOfSight(model, start, end))
4712                         return true;
4713         }
4714
4715         return false;
4716 }
4717
4718
4719 static void R_View_UpdateEntityVisible (void)
4720 {
4721         int i;
4722         int renderimask;
4723         int samples;
4724         entity_render_t *ent;
4725
4726         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4727                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4728                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4729                 :                                                          RENDER_EXTERIORMODEL;
4730         if (!r_drawviewmodel.integer)
4731                 renderimask |= RENDER_VIEWMODEL;
4732         if (!r_drawexteriormodel.integer)
4733                 renderimask |= RENDER_EXTERIORMODEL;
4734         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4735         {
4736                 // worldmodel can check visibility
4737                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4738                 for (i = 0;i < r_refdef.scene.numentities;i++)
4739                 {
4740                         ent = r_refdef.scene.entities[i];
4741                         if (!(ent->flags & renderimask))
4742                         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)))
4743                         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))
4744                                 r_refdef.viewcache.entityvisible[i] = true;
4745                 }
4746                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4747                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4748                 {
4749                         for (i = 0;i < r_refdef.scene.numentities;i++)
4750                         {
4751                                 ent = r_refdef.scene.entities[i];
4752                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4753                                 {
4754                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4755                                         if (samples < 0)
4756                                                 continue; // temp entities do pvs only
4757                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4758                                                 ent->last_trace_visibility = realtime;
4759                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4760                                                 r_refdef.viewcache.entityvisible[i] = 0;
4761                                 }
4762                         }
4763                 }
4764         }
4765         else
4766         {
4767                 // no worldmodel or it can't check visibility
4768                 for (i = 0;i < r_refdef.scene.numentities;i++)
4769                 {
4770                         ent = r_refdef.scene.entities[i];
4771                         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));
4772                 }
4773         }
4774 }
4775
4776 /// only used if skyrendermasked, and normally returns false
4777 int R_DrawBrushModelsSky (void)
4778 {
4779         int i, sky;
4780         entity_render_t *ent;
4781
4782         sky = false;
4783         for (i = 0;i < r_refdef.scene.numentities;i++)
4784         {
4785                 if (!r_refdef.viewcache.entityvisible[i])
4786                         continue;
4787                 ent = r_refdef.scene.entities[i];
4788                 if (!ent->model || !ent->model->DrawSky)
4789                         continue;
4790                 ent->model->DrawSky(ent);
4791                 sky = true;
4792         }
4793         return sky;
4794 }
4795
4796 static void R_DrawNoModel(entity_render_t *ent);
4797 static void R_DrawModels(void)
4798 {
4799         int i;
4800         entity_render_t *ent;
4801
4802         for (i = 0;i < r_refdef.scene.numentities;i++)
4803         {
4804                 if (!r_refdef.viewcache.entityvisible[i])
4805                         continue;
4806                 ent = r_refdef.scene.entities[i];
4807                 r_refdef.stats.entities++;
4808                 if (ent->model && ent->model->Draw != NULL)
4809                         ent->model->Draw(ent);
4810                 else
4811                         R_DrawNoModel(ent);
4812         }
4813 }
4814
4815 static void R_DrawModelsDepth(void)
4816 {
4817         int i;
4818         entity_render_t *ent;
4819
4820         for (i = 0;i < r_refdef.scene.numentities;i++)
4821         {
4822                 if (!r_refdef.viewcache.entityvisible[i])
4823                         continue;
4824                 ent = r_refdef.scene.entities[i];
4825                 if (ent->model && ent->model->DrawDepth != NULL)
4826                         ent->model->DrawDepth(ent);
4827         }
4828 }
4829
4830 static void R_DrawModelsDebug(void)
4831 {
4832         int i;
4833         entity_render_t *ent;
4834
4835         for (i = 0;i < r_refdef.scene.numentities;i++)
4836         {
4837                 if (!r_refdef.viewcache.entityvisible[i])
4838                         continue;
4839                 ent = r_refdef.scene.entities[i];
4840                 if (ent->model && ent->model->DrawDebug != NULL)
4841                         ent->model->DrawDebug(ent);
4842         }
4843 }
4844
4845 static void R_DrawModelsAddWaterPlanes(void)
4846 {
4847         int i;
4848         entity_render_t *ent;
4849
4850         for (i = 0;i < r_refdef.scene.numentities;i++)
4851         {
4852                 if (!r_refdef.viewcache.entityvisible[i])
4853                         continue;
4854                 ent = r_refdef.scene.entities[i];
4855                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4856                         ent->model->DrawAddWaterPlanes(ent);
4857         }
4858 }
4859
4860 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4861 {
4862         if (r_hdr_irisadaptation.integer)
4863         {
4864                 vec3_t ambient;
4865                 vec3_t diffuse;
4866                 vec3_t diffusenormal;
4867                 vec_t brightness;
4868                 vec_t goal;
4869                 vec_t adjust;
4870                 vec_t current;
4871                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4872                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4873                 brightness = max(0.0000001f, brightness);
4874                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4875                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4876                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4877                 current = r_hdr_irisadaptation_value.value;
4878                 if (current < goal)
4879                         current = min(current + adjust, goal);
4880                 else if (current > goal)
4881                         current = max(current - adjust, goal);
4882                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4883                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4884         }
4885         else if (r_hdr_irisadaptation_value.value != 1.0f)
4886                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4887 }
4888
4889 static void R_View_SetFrustum(const int *scissor)
4890 {
4891         int i;
4892         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4893         vec3_t forward, left, up, origin, v;
4894
4895         if(scissor)
4896         {
4897                 // flipped x coordinates (because x points left here)
4898                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4899                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4900
4901                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4902                 switch(vid.renderpath)
4903                 {
4904                         case RENDERPATH_D3D9:
4905                         case RENDERPATH_D3D10:
4906                         case RENDERPATH_D3D11:
4907                         case RENDERPATH_SOFT:
4908                                 // non-flipped y coordinates
4909                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4910                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4911                                 break;
4912                         case RENDERPATH_GL11:
4913                         case RENDERPATH_GL13:
4914                         case RENDERPATH_GL20:
4915                         case RENDERPATH_GLES2:
4916                                 // non-flipped y coordinates
4917                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4918                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4919                                 break;
4920                 }
4921         }
4922
4923         // we can't trust r_refdef.view.forward and friends in reflected scenes
4924         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4925
4926 #if 0
4927         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4928         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4929         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4930         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4931         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4932         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4933         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4934         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4935         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4936         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4937         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4938         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4939 #endif
4940
4941 #if 0
4942         zNear = r_refdef.nearclip;
4943         nudge = 1.0 - 1.0 / (1<<23);
4944         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4945         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4946         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4947         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4948         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4949         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4950         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4951         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4952 #endif
4953
4954
4955
4956 #if 0
4957         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4958         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4959         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4960         r_refdef.view.frustum[0].dist = m[15] - m[12];
4961
4962         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4963         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4964         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4965         r_refdef.view.frustum[1].dist = m[15] + m[12];
4966
4967         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4968         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4969         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4970         r_refdef.view.frustum[2].dist = m[15] - m[13];
4971
4972         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4973         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4974         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4975         r_refdef.view.frustum[3].dist = m[15] + m[13];
4976
4977         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4978         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4979         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4980         r_refdef.view.frustum[4].dist = m[15] - m[14];
4981
4982         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4983         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4984         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4985         r_refdef.view.frustum[5].dist = m[15] + m[14];
4986 #endif
4987
4988         if (r_refdef.view.useperspective)
4989         {
4990                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4991                 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]);
4992                 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]);
4993                 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]);
4994                 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]);
4995
4996                 // then the normals from the corners relative to origin
4997                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4998                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4999                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5000                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5001
5002                 // in a NORMAL view, forward cross left == up
5003                 // in a REFLECTED view, forward cross left == down
5004                 // so our cross products above need to be adjusted for a left handed coordinate system
5005                 CrossProduct(forward, left, v);
5006                 if(DotProduct(v, up) < 0)
5007                 {
5008                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5009                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5010                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5011                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5012                 }
5013
5014                 // Leaving those out was a mistake, those were in the old code, and they
5015                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5016                 // I couldn't reproduce it after adding those normalizations. --blub
5017                 VectorNormalize(r_refdef.view.frustum[0].normal);
5018                 VectorNormalize(r_refdef.view.frustum[1].normal);
5019                 VectorNormalize(r_refdef.view.frustum[2].normal);
5020                 VectorNormalize(r_refdef.view.frustum[3].normal);
5021
5022                 // make the corners absolute
5023                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5024                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5025                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5026                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5027
5028                 // one more normal
5029                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5030
5031                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5032                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5033                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5034                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5035                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5036         }
5037         else
5038         {
5039                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5040                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5041                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5042                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5043                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5044                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5045                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5046                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5047                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5048                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5049         }
5050         r_refdef.view.numfrustumplanes = 5;
5051
5052         if (r_refdef.view.useclipplane)
5053         {
5054                 r_refdef.view.numfrustumplanes = 6;
5055                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5056         }
5057
5058         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5059                 PlaneClassify(r_refdef.view.frustum + i);
5060
5061         // LordHavoc: note to all quake engine coders, Quake had a special case
5062         // for 90 degrees which assumed a square view (wrong), so I removed it,
5063         // Quake2 has it disabled as well.
5064
5065         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5066         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5067         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5068         //PlaneClassify(&frustum[0]);
5069
5070         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5071         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5072         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5073         //PlaneClassify(&frustum[1]);
5074
5075         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5076         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5077         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5078         //PlaneClassify(&frustum[2]);
5079
5080         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5081         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5082         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5083         //PlaneClassify(&frustum[3]);
5084
5085         // nearclip plane
5086         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5087         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5088         //PlaneClassify(&frustum[4]);
5089 }
5090
5091 void R_View_UpdateWithScissor(const int *myscissor)
5092 {
5093         R_Main_ResizeViewCache();
5094         R_View_SetFrustum(myscissor);
5095         R_View_WorldVisibility(r_refdef.view.useclipplane);
5096         R_View_UpdateEntityVisible();
5097         R_View_UpdateEntityLighting();
5098 }
5099
5100 void R_View_Update(void)
5101 {
5102         R_Main_ResizeViewCache();
5103         R_View_SetFrustum(NULL);
5104         R_View_WorldVisibility(r_refdef.view.useclipplane);
5105         R_View_UpdateEntityVisible();
5106         R_View_UpdateEntityLighting();
5107 }
5108
5109 void R_SetupView(qboolean allowwaterclippingplane)
5110 {
5111         const float *customclipplane = NULL;
5112         float plane[4];
5113         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5114         {
5115                 // LordHavoc: couldn't figure out how to make this approach the
5116                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5117                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5118                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5119                         dist = r_refdef.view.clipplane.dist;
5120                 plane[0] = r_refdef.view.clipplane.normal[0];
5121                 plane[1] = r_refdef.view.clipplane.normal[1];
5122                 plane[2] = r_refdef.view.clipplane.normal[2];
5123                 plane[3] = dist;
5124                 customclipplane = plane;
5125         }
5126
5127         if (!r_refdef.view.useperspective)
5128                 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);
5129         else if (vid.stencil && r_useinfinitefarclip.integer)
5130                 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);
5131         else
5132                 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);
5133         R_SetViewport(&r_refdef.view.viewport);
5134 }
5135
5136 void R_EntityMatrix(const matrix4x4_t *matrix)
5137 {
5138         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5139         {
5140                 gl_modelmatrixchanged = false;
5141                 gl_modelmatrix = *matrix;
5142                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5143                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5144                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5145                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5146                 CHECKGLERROR
5147                 switch(vid.renderpath)
5148                 {
5149                 case RENDERPATH_D3D9:
5150 #ifdef SUPPORTD3D
5151                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5152                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5153 #endif
5154                         break;
5155                 case RENDERPATH_D3D10:
5156                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5157                         break;
5158                 case RENDERPATH_D3D11:
5159                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5160                         break;
5161                 case RENDERPATH_GL13:
5162                 case RENDERPATH_GL11:
5163                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5164                         break;
5165                 case RENDERPATH_SOFT:
5166                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5167                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5168                         break;
5169                 case RENDERPATH_GL20:
5170                 case RENDERPATH_GLES2:
5171                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5172                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5173                         break;
5174                 }
5175         }
5176 }
5177
5178 void R_ResetViewRendering2D(void)
5179 {
5180         r_viewport_t viewport;
5181         DrawQ_Finish();
5182
5183         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5184         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);
5185         R_SetViewport(&viewport);
5186         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5187         GL_Color(1, 1, 1, 1);
5188         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5189         GL_BlendFunc(GL_ONE, GL_ZERO);
5190         GL_ScissorTest(false);
5191         GL_DepthMask(false);
5192         GL_DepthRange(0, 1);
5193         GL_DepthTest(false);
5194         GL_DepthFunc(GL_LEQUAL);
5195         R_EntityMatrix(&identitymatrix);
5196         R_Mesh_ResetTextureState();
5197         GL_PolygonOffset(0, 0);
5198         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5199         switch(vid.renderpath)
5200         {
5201         case RENDERPATH_GL11:
5202         case RENDERPATH_GL13:
5203         case RENDERPATH_GL20:
5204         case RENDERPATH_GLES2:
5205                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5206                 break;
5207         case RENDERPATH_D3D9:
5208         case RENDERPATH_D3D10:
5209         case RENDERPATH_D3D11:
5210         case RENDERPATH_SOFT:
5211                 break;
5212         }
5213         GL_CullFace(GL_NONE);
5214 }
5215
5216 void R_ResetViewRendering3D(void)
5217 {
5218         DrawQ_Finish();
5219
5220         R_SetupView(true);
5221         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5222         GL_Color(1, 1, 1, 1);
5223         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5224         GL_BlendFunc(GL_ONE, GL_ZERO);
5225         GL_ScissorTest(true);
5226         GL_DepthMask(true);
5227         GL_DepthRange(0, 1);
5228         GL_DepthTest(true);
5229         GL_DepthFunc(GL_LEQUAL);
5230         R_EntityMatrix(&identitymatrix);
5231         R_Mesh_ResetTextureState();
5232         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5233         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5234         switch(vid.renderpath)
5235         {
5236         case RENDERPATH_GL11:
5237         case RENDERPATH_GL13:
5238         case RENDERPATH_GL20:
5239         case RENDERPATH_GLES2:
5240                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5241                 break;
5242         case RENDERPATH_D3D9:
5243         case RENDERPATH_D3D10:
5244         case RENDERPATH_D3D11:
5245         case RENDERPATH_SOFT:
5246                 break;
5247         }
5248         GL_CullFace(r_refdef.view.cullface_back);
5249 }
5250
5251 /*
5252 ================
5253 R_RenderView_UpdateViewVectors
5254 ================
5255 */
5256 static void R_RenderView_UpdateViewVectors(void)
5257 {
5258         // break apart the view matrix into vectors for various purposes
5259         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5260         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5261         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5262         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5263         // make an inverted copy of the view matrix for tracking sprites
5264         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5265 }
5266
5267 void R_RenderScene(void);
5268 void R_RenderWaterPlanes(void);
5269
5270 static void R_Water_StartFrame(void)
5271 {
5272         int i;
5273         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5274         r_waterstate_waterplane_t *p;
5275
5276         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5277                 return;
5278
5279         switch(vid.renderpath)
5280         {
5281         case RENDERPATH_GL20:
5282         case RENDERPATH_D3D9:
5283         case RENDERPATH_D3D10:
5284         case RENDERPATH_D3D11:
5285         case RENDERPATH_SOFT:
5286         case RENDERPATH_GLES2:
5287                 break;
5288         case RENDERPATH_GL13:
5289         case RENDERPATH_GL11:
5290                 return;
5291         }
5292
5293         // set waterwidth and waterheight to the water resolution that will be
5294         // used (often less than the screen resolution for faster rendering)
5295         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5296         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5297
5298         // calculate desired texture sizes
5299         // can't use water if the card does not support the texture size
5300         if (!r_water.integer || r_showsurfaces.integer)
5301                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5302         else if (vid.support.arb_texture_non_power_of_two)
5303         {
5304                 texturewidth = waterwidth;
5305                 textureheight = waterheight;
5306                 camerawidth = waterwidth;
5307                 cameraheight = waterheight;
5308         }
5309         else
5310         {
5311                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5312                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5313                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5314                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5315         }
5316
5317         // allocate textures as needed
5318         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5319         {
5320                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5321                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5322                 {
5323                         if (p->texture_refraction)
5324                                 R_FreeTexture(p->texture_refraction);
5325                         p->texture_refraction = NULL;
5326                         if (p->texture_reflection)
5327                                 R_FreeTexture(p->texture_reflection);
5328                         p->texture_reflection = NULL;
5329                         if (p->texture_camera)
5330                                 R_FreeTexture(p->texture_camera);
5331                         p->texture_camera = NULL;
5332                 }
5333                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5334                 r_waterstate.texturewidth = texturewidth;
5335                 r_waterstate.textureheight = textureheight;
5336                 r_waterstate.camerawidth = camerawidth;
5337                 r_waterstate.cameraheight = cameraheight;
5338         }
5339
5340         if (r_waterstate.texturewidth)
5341         {
5342                 r_waterstate.enabled = true;
5343
5344                 // when doing a reduced render (HDR) we want to use a smaller area
5345                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5346                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5347
5348                 // set up variables that will be used in shader setup
5349                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5350                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5351                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5352                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5353         }
5354
5355         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5356         r_waterstate.numwaterplanes = 0;
5357 }
5358
5359 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5360 {
5361         int triangleindex, planeindex;
5362         const int *e;
5363         vec3_t vert[3];
5364         vec3_t normal;
5365         vec3_t center;
5366         mplane_t plane;
5367         r_waterstate_waterplane_t *p;
5368         texture_t *t = R_GetCurrentTexture(surface->texture);
5369
5370         // just use the first triangle with a valid normal for any decisions
5371         VectorClear(normal);
5372         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5373         {
5374                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5375                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5376                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5377                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5378                 if (VectorLength2(normal) >= 0.001)
5379                         break;
5380         }
5381
5382         VectorCopy(normal, plane.normal);
5383         VectorNormalize(plane.normal);
5384         plane.dist = DotProduct(vert[0], plane.normal);
5385         PlaneClassify(&plane);
5386         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5387         {
5388                 // skip backfaces (except if nocullface is set)
5389                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5390                         return;
5391                 VectorNegate(plane.normal, plane.normal);
5392                 plane.dist *= -1;
5393                 PlaneClassify(&plane);
5394         }
5395
5396
5397         // find a matching plane if there is one
5398         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5399                 if(p->camera_entity == t->camera_entity)
5400                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5401                                 break;
5402         if (planeindex >= r_waterstate.maxwaterplanes)
5403                 return; // nothing we can do, out of planes
5404
5405         // if this triangle does not fit any known plane rendered this frame, add one
5406         if (planeindex >= r_waterstate.numwaterplanes)
5407         {
5408                 // store the new plane
5409                 r_waterstate.numwaterplanes++;
5410                 p->plane = plane;
5411                 // clear materialflags and pvs
5412                 p->materialflags = 0;
5413                 p->pvsvalid = false;
5414                 p->camera_entity = t->camera_entity;
5415                 VectorCopy(surface->mins, p->mins);
5416                 VectorCopy(surface->maxs, p->maxs);
5417         }
5418         else
5419         {
5420                 // merge mins/maxs
5421                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5422                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5423                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5424                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5425                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5426                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5427         }
5428         // merge this surface's materialflags into the waterplane
5429         p->materialflags |= t->currentmaterialflags;
5430         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5431         {
5432                 // merge this surface's PVS into the waterplane
5433                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5434                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5435                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5436                 {
5437                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5438                         p->pvsvalid = true;
5439                 }
5440         }
5441 }
5442
5443 static void R_Water_ProcessPlanes(void)
5444 {
5445         int myscissor[4];
5446         r_refdef_view_t originalview;
5447         r_refdef_view_t myview;
5448         int planeindex;
5449         r_waterstate_waterplane_t *p;
5450         vec3_t visorigin;
5451
5452         originalview = r_refdef.view;
5453
5454         // make sure enough textures are allocated
5455         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5456         {
5457                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5458                 {
5459                         if (!p->texture_refraction)
5460                                 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);
5461                         if (!p->texture_refraction)
5462                                 goto error;
5463                 }
5464                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5465                 {
5466                         if (!p->texture_camera)
5467                                 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);
5468                         if (!p->texture_camera)
5469                                 goto error;
5470                 }
5471
5472                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5473                 {
5474                         if (!p->texture_reflection)
5475                                 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);
5476                         if (!p->texture_reflection)
5477                                 goto error;
5478                 }
5479         }
5480
5481         // render views
5482         r_refdef.view = originalview;
5483         r_refdef.view.showdebug = false;
5484         r_refdef.view.width = r_waterstate.waterwidth;
5485         r_refdef.view.height = r_waterstate.waterheight;
5486         r_refdef.view.useclipplane = true;
5487         myview = r_refdef.view;
5488         r_waterstate.renderingscene = true;
5489         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5490         {
5491                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5492                 {
5493                         r_refdef.view = myview;
5494                         if(r_water_scissormode.integer)
5495                         {
5496                                 R_SetupView(true);
5497                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5498                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5499                         }
5500
5501                         // render reflected scene and copy into texture
5502                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5503                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5504                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5505                         r_refdef.view.clipplane = p->plane;
5506
5507                         // reverse the cullface settings for this render
5508                         r_refdef.view.cullface_front = GL_FRONT;
5509                         r_refdef.view.cullface_back = GL_BACK;
5510                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5511                         {
5512                                 r_refdef.view.usecustompvs = true;
5513                                 if (p->pvsvalid)
5514                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5515                                 else
5516                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5517                         }
5518
5519                         R_ResetViewRendering3D();
5520                         R_ClearScreen(r_refdef.fogenabled);
5521                         if(r_water_scissormode.integer & 2)
5522                                 R_View_UpdateWithScissor(myscissor);
5523                         else
5524                                 R_View_Update();
5525                         if(r_water_scissormode.integer & 1)
5526                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5527                         R_RenderScene();
5528
5529                         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);
5530                 }
5531
5532                 // render the normal view scene and copy into texture
5533                 // (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)
5534                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5535                 {
5536                         r_refdef.view = myview;
5537                         if(r_water_scissormode.integer)
5538                         {
5539                                 R_SetupView(true);
5540                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5541                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5542                         }
5543
5544                         r_waterstate.renderingrefraction = true;
5545
5546                         r_refdef.view.clipplane = p->plane;
5547                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5548                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5549
5550                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5551                         {
5552                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5553                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5554                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5555                                 R_RenderView_UpdateViewVectors();
5556                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5557                                 {
5558                                         r_refdef.view.usecustompvs = true;
5559                                         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);
5560                                 }
5561                         }
5562
5563                         PlaneClassify(&r_refdef.view.clipplane);
5564
5565                         R_ResetViewRendering3D();
5566                         R_ClearScreen(r_refdef.fogenabled);
5567                         if(r_water_scissormode.integer & 2)
5568                                 R_View_UpdateWithScissor(myscissor);
5569                         else
5570                                 R_View_Update();
5571                         if(r_water_scissormode.integer & 1)
5572                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5573                         R_RenderScene();
5574
5575                         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);
5576                         r_waterstate.renderingrefraction = false;
5577                 }
5578                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5579                 {
5580                         r_refdef.view = myview;
5581
5582                         r_refdef.view.clipplane = p->plane;
5583                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5584                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5585
5586                         r_refdef.view.width = r_waterstate.camerawidth;
5587                         r_refdef.view.height = r_waterstate.cameraheight;
5588                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5589                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5590
5591                         if(p->camera_entity)
5592                         {
5593                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5594                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5595                         }
5596
5597                         // note: all of the view is used for displaying... so
5598                         // there is no use in scissoring
5599
5600                         // reverse the cullface settings for this render
5601                         r_refdef.view.cullface_front = GL_FRONT;
5602                         r_refdef.view.cullface_back = GL_BACK;
5603                         // also reverse the view matrix
5604                         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
5605                         R_RenderView_UpdateViewVectors();
5606                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5607                         {
5608                                 r_refdef.view.usecustompvs = true;
5609                                 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);
5610                         }
5611                         
5612                         // camera needs no clipplane
5613                         r_refdef.view.useclipplane = false;
5614
5615                         PlaneClassify(&r_refdef.view.clipplane);
5616
5617                         R_ResetViewRendering3D();
5618                         R_ClearScreen(r_refdef.fogenabled);
5619                         R_View_Update();
5620                         R_RenderScene();
5621
5622                         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);
5623                         r_waterstate.renderingrefraction = false;
5624                 }
5625
5626         }
5627         r_waterstate.renderingscene = false;
5628         r_refdef.view = originalview;
5629         R_ResetViewRendering3D();
5630         R_ClearScreen(r_refdef.fogenabled);
5631         R_View_Update();
5632         return;
5633 error:
5634         r_refdef.view = originalview;
5635         r_waterstate.renderingscene = false;
5636         Cvar_SetValueQuick(&r_water, 0);
5637         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5638         return;
5639 }
5640
5641 void R_Bloom_StartFrame(void)
5642 {
5643         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5644
5645         switch(vid.renderpath)
5646         {
5647         case RENDERPATH_GL20:
5648         case RENDERPATH_D3D9:
5649         case RENDERPATH_D3D10:
5650         case RENDERPATH_D3D11:
5651         case RENDERPATH_SOFT:
5652         case RENDERPATH_GLES2:
5653                 break;
5654         case RENDERPATH_GL13:
5655         case RENDERPATH_GL11:
5656                 return;
5657         }
5658
5659         // set bloomwidth and bloomheight to the bloom resolution that will be
5660         // used (often less than the screen resolution for faster rendering)
5661         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5662         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5663         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5664         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5665         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5666
5667         // calculate desired texture sizes
5668         if (vid.support.arb_texture_non_power_of_two)
5669         {
5670                 screentexturewidth = r_refdef.view.width;
5671                 screentextureheight = r_refdef.view.height;
5672                 bloomtexturewidth = r_bloomstate.bloomwidth;
5673                 bloomtextureheight = r_bloomstate.bloomheight;
5674         }
5675         else
5676         {
5677                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5678                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5679                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5680                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5681         }
5682
5683         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))
5684         {
5685                 Cvar_SetValueQuick(&r_hdr, 0);
5686                 Cvar_SetValueQuick(&r_bloom, 0);
5687                 Cvar_SetValueQuick(&r_motionblur, 0);
5688                 Cvar_SetValueQuick(&r_damageblur, 0);
5689         }
5690
5691         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)))
5692                 screentexturewidth = screentextureheight = 0;
5693         if (!r_hdr.integer && !r_bloom.integer)
5694                 bloomtexturewidth = bloomtextureheight = 0;
5695
5696         // allocate textures as needed
5697         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5698         {
5699                 if (r_bloomstate.texture_screen)
5700                         R_FreeTexture(r_bloomstate.texture_screen);
5701                 r_bloomstate.texture_screen = NULL;
5702                 r_bloomstate.screentexturewidth = screentexturewidth;
5703                 r_bloomstate.screentextureheight = screentextureheight;
5704                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5705                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
5706         }
5707         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5708         {
5709                 if (r_bloomstate.texture_bloom)
5710                         R_FreeTexture(r_bloomstate.texture_bloom);
5711                 r_bloomstate.texture_bloom = NULL;
5712                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5713                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5714                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5715                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5716         }
5717
5718         // when doing a reduced render (HDR) we want to use a smaller area
5719         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5720         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5721         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5722         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5723         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5724
5725         // set up a texcoord array for the full resolution screen image
5726         // (we have to keep this around to copy back during final render)
5727         r_bloomstate.screentexcoord2f[0] = 0;
5728         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5729         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5730         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5731         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5732         r_bloomstate.screentexcoord2f[5] = 0;
5733         r_bloomstate.screentexcoord2f[6] = 0;
5734         r_bloomstate.screentexcoord2f[7] = 0;
5735
5736         // set up a texcoord array for the reduced resolution bloom image
5737         // (which will be additive blended over the screen image)
5738         r_bloomstate.bloomtexcoord2f[0] = 0;
5739         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5740         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5741         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5742         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5743         r_bloomstate.bloomtexcoord2f[5] = 0;
5744         r_bloomstate.bloomtexcoord2f[6] = 0;
5745         r_bloomstate.bloomtexcoord2f[7] = 0;
5746
5747         switch(vid.renderpath)
5748         {
5749         case RENDERPATH_GL11:
5750         case RENDERPATH_GL13:
5751         case RENDERPATH_GL20:
5752         case RENDERPATH_SOFT:
5753         case RENDERPATH_GLES2:
5754                 break;
5755         case RENDERPATH_D3D9:
5756         case RENDERPATH_D3D10:
5757         case RENDERPATH_D3D11:
5758                 {
5759                         int i;
5760                         for (i = 0;i < 4;i++)
5761                         {
5762                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5763                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5764                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5765                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5766                         }
5767                 }
5768                 break;
5769         }
5770
5771         if (r_hdr.integer || r_bloom.integer)
5772         {
5773                 r_bloomstate.enabled = true;
5774                 r_bloomstate.hdr = r_hdr.integer != 0;
5775         }
5776
5777         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);
5778 }
5779
5780 void R_Bloom_CopyBloomTexture(float colorscale)
5781 {
5782         r_refdef.stats.bloom++;
5783
5784         // scale down screen texture to the bloom texture size
5785         CHECKGLERROR
5786         R_SetViewport(&r_bloomstate.viewport);
5787         GL_BlendFunc(GL_ONE, GL_ZERO);
5788         GL_Color(colorscale, colorscale, colorscale, 1);
5789         // 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...
5790         switch(vid.renderpath)
5791         {
5792         case RENDERPATH_GL11:
5793         case RENDERPATH_GL13:
5794         case RENDERPATH_GL20:
5795         case RENDERPATH_SOFT:
5796         case RENDERPATH_GLES2:
5797                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5798                 break;
5799         case RENDERPATH_D3D9:
5800         case RENDERPATH_D3D10:
5801         case RENDERPATH_D3D11:
5802                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5803                 break;
5804         }
5805         // TODO: do boxfilter scale-down in shader?
5806         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5807         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5808         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5809
5810         // we now have a bloom image in the framebuffer
5811         // copy it into the bloom image texture for later processing
5812         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);
5813         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5814 }
5815
5816 void R_Bloom_CopyHDRTexture(void)
5817 {
5818         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);
5819         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5820 }
5821
5822 void R_Bloom_MakeTexture(void)
5823 {
5824         int x, range, dir;
5825         float xoffset, yoffset, r, brighten;
5826
5827         r_refdef.stats.bloom++;
5828
5829         R_ResetViewRendering2D();
5830
5831         // we have a bloom image in the framebuffer
5832         CHECKGLERROR
5833         R_SetViewport(&r_bloomstate.viewport);
5834
5835         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5836         {
5837                 x *= 2;
5838                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5839                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5840                 GL_Color(r,r,r,1);
5841                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5842                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5843                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5844                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5845
5846                 // copy the vertically blurred bloom view to a texture
5847                 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);
5848                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5849         }
5850
5851         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5852         brighten = r_bloom_brighten.value;
5853         if (r_hdr.integer)
5854                 brighten *= r_hdr_range.value;
5855         brighten = sqrt(brighten);
5856         if(range >= 1)
5857                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5858         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5859
5860         for (dir = 0;dir < 2;dir++)
5861         {
5862                 // blend on at multiple vertical offsets to achieve a vertical blur
5863                 // TODO: do offset blends using GLSL
5864                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5865                 GL_BlendFunc(GL_ONE, GL_ZERO);
5866                 for (x = -range;x <= range;x++)
5867                 {
5868                         if (!dir){xoffset = 0;yoffset = x;}
5869                         else {xoffset = x;yoffset = 0;}
5870                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5871                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5872                         // compute a texcoord array with the specified x and y offset
5873                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5874                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5875                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5876                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5877                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5878                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5879                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5880                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5881                         // this r value looks like a 'dot' particle, fading sharply to
5882                         // black at the edges
5883                         // (probably not realistic but looks good enough)
5884                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5885                         //r = brighten/(range*2+1);
5886                         r = brighten / (range * 2 + 1);
5887                         if(range >= 1)
5888                                 r *= (1 - x*x/(float)(range*range));
5889                         GL_Color(r, r, r, 1);
5890                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5891                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5892                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5893                         GL_BlendFunc(GL_ONE, GL_ONE);
5894                 }
5895
5896                 // copy the vertically blurred bloom view to a texture
5897                 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);
5898                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5899         }
5900 }
5901
5902 void R_HDR_RenderBloomTexture(void)
5903 {
5904         int oldwidth, oldheight;
5905         float oldcolorscale;
5906         qboolean oldwaterstate;
5907
5908         oldwaterstate = r_waterstate.enabled;
5909         oldcolorscale = r_refdef.view.colorscale;
5910         oldwidth = r_refdef.view.width;
5911         oldheight = r_refdef.view.height;
5912         r_refdef.view.width = r_bloomstate.bloomwidth;
5913         r_refdef.view.height = r_bloomstate.bloomheight;
5914
5915         if(r_hdr.integer < 2)
5916                 r_waterstate.enabled = false;
5917
5918         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5919         // TODO: add exposure compensation features
5920         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5921
5922         r_refdef.view.showdebug = false;
5923         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5924
5925         R_ResetViewRendering3D();
5926
5927         R_ClearScreen(r_refdef.fogenabled);
5928         if (r_timereport_active)
5929                 R_TimeReport("HDRclear");
5930
5931         R_View_Update();
5932         if (r_timereport_active)
5933                 R_TimeReport("visibility");
5934
5935         // only do secondary renders with HDR if r_hdr is 2 or higher
5936         r_waterstate.numwaterplanes = 0;
5937         if (r_waterstate.enabled)
5938                 R_RenderWaterPlanes();
5939
5940         r_refdef.view.showdebug = true;
5941         R_RenderScene();
5942         r_waterstate.numwaterplanes = 0;
5943
5944         R_ResetViewRendering2D();
5945
5946         R_Bloom_CopyHDRTexture();
5947         R_Bloom_MakeTexture();
5948
5949         // restore the view settings
5950         r_waterstate.enabled = oldwaterstate;
5951         r_refdef.view.width = oldwidth;
5952         r_refdef.view.height = oldheight;
5953         r_refdef.view.colorscale = oldcolorscale;
5954
5955         R_ResetViewRendering3D();
5956
5957         R_ClearScreen(r_refdef.fogenabled);
5958         if (r_timereport_active)
5959                 R_TimeReport("viewclear");
5960 }
5961
5962 static void R_BlendView(void)
5963 {
5964         unsigned int permutation;
5965         float uservecs[4][4];
5966
5967         switch (vid.renderpath)
5968         {
5969         case RENDERPATH_GL20:
5970         case RENDERPATH_D3D9:
5971         case RENDERPATH_D3D10:
5972         case RENDERPATH_D3D11:
5973         case RENDERPATH_SOFT:
5974         case RENDERPATH_GLES2:
5975                 permutation =
5976                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5977                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5978                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5979                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5980                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5981
5982                 if (r_bloomstate.texture_screen)
5983                 {
5984                         // make sure the buffer is available
5985                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5986
5987                         R_ResetViewRendering2D();
5988
5989                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5990                         {
5991                                 // declare variables
5992                                 float speed;
5993                                 static float avgspeed;
5994
5995                                 speed = VectorLength(cl.movement_velocity);
5996
5997                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5998                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5999
6000                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6001                                 speed = bound(0, speed, 1);
6002                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6003
6004                                 // calculate values into a standard alpha
6005                                 cl.motionbluralpha = 1 - exp(-
6006                                                 (
6007                                                  (r_motionblur.value * speed / 80)
6008                                                  +
6009                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6010                                                 )
6011                                                 /
6012                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6013                                            );
6014
6015                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6016                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6017                                 // apply the blur
6018                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6019                                 {
6020                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6021                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6022                                         switch(vid.renderpath)
6023                                         {
6024                                         case RENDERPATH_GL11:
6025                                         case RENDERPATH_GL13:
6026                                         case RENDERPATH_GL20:
6027                                         case RENDERPATH_SOFT:
6028                                         case RENDERPATH_GLES2:
6029                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6030                                                 break;
6031                                         case RENDERPATH_D3D9:
6032                                         case RENDERPATH_D3D10:
6033                                         case RENDERPATH_D3D11:
6034                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6035                                                 break;
6036                                         }
6037                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6038                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6039                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6040                                 }
6041                         }
6042
6043                         // copy view into the screen texture
6044                         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);
6045                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6046                 }
6047                 else if (!r_bloomstate.texture_bloom)
6048                 {
6049                         // we may still have to do view tint...
6050                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6051                         {
6052                                 // apply a color tint to the whole view
6053                                 R_ResetViewRendering2D();
6054                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6055                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6056                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6057                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6058                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6059                         }
6060                         break; // no screen processing, no bloom, skip it
6061                 }
6062
6063                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6064                 {
6065                         // render simple bloom effect
6066                         // copy the screen and shrink it and darken it for the bloom process
6067                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6068                         // make the bloom texture
6069                         R_Bloom_MakeTexture();
6070                 }
6071
6072 #if _MSC_VER >= 1400
6073 #define sscanf sscanf_s
6074 #endif
6075                 memset(uservecs, 0, sizeof(uservecs));
6076                 if (r_glsl_postprocess_uservec1_enable.integer)
6077                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6078                 if (r_glsl_postprocess_uservec2_enable.integer)
6079                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6080                 if (r_glsl_postprocess_uservec3_enable.integer)
6081                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6082                 if (r_glsl_postprocess_uservec4_enable.integer)
6083                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6084
6085                 R_ResetViewRendering2D();
6086                 GL_Color(1, 1, 1, 1);
6087                 GL_BlendFunc(GL_ONE, GL_ZERO);
6088
6089                 switch(vid.renderpath)
6090                 {
6091                 case RENDERPATH_GL20:
6092                 case RENDERPATH_GLES2:
6093                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6094                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6095                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6096                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6097                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6098                         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]);
6099                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6100                         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]);
6101                         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]);
6102                         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]);
6103                         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]);
6104                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6105                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6106                         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);
6107                         break;
6108                 case RENDERPATH_D3D9:
6109 #ifdef SUPPORTD3D
6110                         // 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...
6111                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6112                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6113                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6114                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6115                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6116                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6117                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6118                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6119                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6120                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6121                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6122                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6123                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6124                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6125 #endif
6126                         break;
6127                 case RENDERPATH_D3D10:
6128                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6129                         break;
6130                 case RENDERPATH_D3D11:
6131                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6132                         break;
6133                 case RENDERPATH_SOFT:
6134                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6135                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6136                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6137                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6138                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6139                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6140                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6141                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6142                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6143                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6144                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6145                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6146                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6147                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6148                         break;
6149                 default:
6150                         break;
6151                 }
6152                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6153                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6154                 break;
6155         case RENDERPATH_GL13:
6156         case RENDERPATH_GL11:
6157                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6158                 {
6159                         // apply a color tint to the whole view
6160                         R_ResetViewRendering2D();
6161                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6162                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6163                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6164                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6165                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6166                 }
6167                 break;
6168         }
6169 }
6170
6171 matrix4x4_t r_waterscrollmatrix;
6172
6173 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6174 {
6175         if (r_refdef.fog_density)
6176         {
6177                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6178                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6179                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6180
6181                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6182                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6183                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6184                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6185
6186                 {
6187                         vec3_t fogvec;
6188                         VectorCopy(r_refdef.fogcolor, fogvec);
6189                         //   color.rgb *= ContrastBoost * SceneBrightness;
6190                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6191                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6192                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6193                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6194                 }
6195         }
6196 }
6197
6198 void R_UpdateVariables(void)
6199 {
6200         R_Textures_Frame();
6201
6202         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6203
6204         r_refdef.farclip = r_farclip_base.value;
6205         if (r_refdef.scene.worldmodel)
6206                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6207         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6208
6209         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6210                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6211         r_refdef.polygonfactor = 0;
6212         r_refdef.polygonoffset = 0;
6213         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6214         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6215
6216         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6217         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6218         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6219         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6220         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6221         if (FAKELIGHT_ENABLED)
6222         {
6223                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6224         }
6225         if (r_showsurfaces.integer)
6226         {
6227                 r_refdef.scene.rtworld = false;
6228                 r_refdef.scene.rtworldshadows = false;
6229                 r_refdef.scene.rtdlight = false;
6230                 r_refdef.scene.rtdlightshadows = false;
6231                 r_refdef.lightmapintensity = 0;
6232         }
6233
6234         if (gamemode == GAME_NEHAHRA)
6235         {
6236                 if (gl_fogenable.integer)
6237                 {
6238                         r_refdef.oldgl_fogenable = true;
6239                         r_refdef.fog_density = gl_fogdensity.value;
6240                         r_refdef.fog_red = gl_fogred.value;
6241                         r_refdef.fog_green = gl_foggreen.value;
6242                         r_refdef.fog_blue = gl_fogblue.value;
6243                         r_refdef.fog_alpha = 1;
6244                         r_refdef.fog_start = 0;
6245                         r_refdef.fog_end = gl_skyclip.value;
6246                         r_refdef.fog_height = 1<<30;
6247                         r_refdef.fog_fadedepth = 128;
6248                 }
6249                 else if (r_refdef.oldgl_fogenable)
6250                 {
6251                         r_refdef.oldgl_fogenable = false;
6252                         r_refdef.fog_density = 0;
6253                         r_refdef.fog_red = 0;
6254                         r_refdef.fog_green = 0;
6255                         r_refdef.fog_blue = 0;
6256                         r_refdef.fog_alpha = 0;
6257                         r_refdef.fog_start = 0;
6258                         r_refdef.fog_end = 0;
6259                         r_refdef.fog_height = 1<<30;
6260                         r_refdef.fog_fadedepth = 128;
6261                 }
6262         }
6263
6264         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6265         r_refdef.fog_start = max(0, r_refdef.fog_start);
6266         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6267
6268         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6269
6270         if (r_refdef.fog_density && r_drawfog.integer)
6271         {
6272                 r_refdef.fogenabled = true;
6273                 // this is the point where the fog reaches 0.9986 alpha, which we
6274                 // consider a good enough cutoff point for the texture
6275                 // (0.9986 * 256 == 255.6)
6276                 if (r_fog_exp2.integer)
6277                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6278                 else
6279                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6280                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6281                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6282                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6283                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6284                         R_BuildFogHeightTexture();
6285                 // fog color was already set
6286                 // update the fog texture
6287                 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)
6288                         R_BuildFogTexture();
6289                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6290                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6291         }
6292         else
6293                 r_refdef.fogenabled = false;
6294
6295         switch(vid.renderpath)
6296         {
6297         case RENDERPATH_GL20:
6298         case RENDERPATH_D3D9:
6299         case RENDERPATH_D3D10:
6300         case RENDERPATH_D3D11:
6301         case RENDERPATH_SOFT:
6302         case RENDERPATH_GLES2:
6303                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6304                 {
6305                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6306                         {
6307                                 // build GLSL gamma texture
6308 #define RAMPWIDTH 256
6309                                 unsigned short ramp[RAMPWIDTH * 3];
6310                                 unsigned char rampbgr[RAMPWIDTH][4];
6311                                 int i;
6312
6313                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6314
6315                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6316                                 for(i = 0; i < RAMPWIDTH; ++i)
6317                                 {
6318                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6319                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6320                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6321                                         rampbgr[i][3] = 0;
6322                                 }
6323                                 if (r_texture_gammaramps)
6324                                 {
6325                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6326                                 }
6327                                 else
6328                                 {
6329                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6330                                 }
6331                         }
6332                 }
6333                 else
6334                 {
6335                         // remove GLSL gamma texture
6336                 }
6337                 break;
6338         case RENDERPATH_GL13:
6339         case RENDERPATH_GL11:
6340                 break;
6341         }
6342 }
6343
6344 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6345 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6346 /*
6347 ================
6348 R_SelectScene
6349 ================
6350 */
6351 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6352         if( scenetype != r_currentscenetype ) {
6353                 // store the old scenetype
6354                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6355                 r_currentscenetype = scenetype;
6356                 // move in the new scene
6357                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6358         }
6359 }
6360
6361 /*
6362 ================
6363 R_GetScenePointer
6364 ================
6365 */
6366 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6367 {
6368         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6369         if( scenetype == r_currentscenetype ) {
6370                 return &r_refdef.scene;
6371         } else {
6372                 return &r_scenes_store[ scenetype ];
6373         }
6374 }
6375
6376 /*
6377 ================
6378 R_RenderView
6379 ================
6380 */
6381 int dpsoftrast_test;
6382 void R_RenderView(void)
6383 {
6384         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6385
6386         dpsoftrast_test = r_test.integer;
6387
6388         if (r_timereport_active)
6389                 R_TimeReport("start");
6390         r_textureframe++; // used only by R_GetCurrentTexture
6391         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6392
6393         if(R_CompileShader_CheckStaticParms())
6394                 R_GLSL_Restart_f();
6395
6396         if (!r_drawentities.integer)
6397                 r_refdef.scene.numentities = 0;
6398
6399         R_AnimCache_ClearCache();
6400         R_FrameData_NewFrame();
6401
6402         /* adjust for stereo display */
6403         if(R_Stereo_Active())
6404         {
6405                 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);
6406                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6407         }
6408
6409         if (r_refdef.view.isoverlay)
6410         {
6411                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6412                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6413                 R_TimeReport("depthclear");
6414
6415                 r_refdef.view.showdebug = false;
6416
6417                 r_waterstate.enabled = false;
6418                 r_waterstate.numwaterplanes = 0;
6419
6420                 R_RenderScene();
6421
6422                 r_refdef.view.matrix = originalmatrix;
6423
6424                 CHECKGLERROR
6425                 return;
6426         }
6427
6428         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6429         {
6430                 r_refdef.view.matrix = originalmatrix;
6431                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6432         }
6433
6434         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6435
6436         R_RenderView_UpdateViewVectors();
6437
6438         R_Shadow_UpdateWorldLightSelection();
6439
6440         R_Bloom_StartFrame();
6441         R_Water_StartFrame();
6442
6443         CHECKGLERROR
6444         if (r_timereport_active)
6445                 R_TimeReport("viewsetup");
6446
6447         R_ResetViewRendering3D();
6448
6449         if (r_refdef.view.clear || r_refdef.fogenabled)
6450         {
6451                 R_ClearScreen(r_refdef.fogenabled);
6452                 if (r_timereport_active)
6453                         R_TimeReport("viewclear");
6454         }
6455         r_refdef.view.clear = true;
6456
6457         // this produces a bloom texture to be used in R_BlendView() later
6458         if (r_hdr.integer && r_bloomstate.bloomwidth)
6459         {
6460                 R_HDR_RenderBloomTexture();
6461                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6462                 r_textureframe++; // used only by R_GetCurrentTexture
6463         }
6464
6465         r_refdef.view.showdebug = true;
6466
6467         R_View_Update();
6468         if (r_timereport_active)
6469                 R_TimeReport("visibility");
6470
6471         r_waterstate.numwaterplanes = 0;
6472         if (r_waterstate.enabled)
6473                 R_RenderWaterPlanes();
6474
6475         R_RenderScene();
6476         r_waterstate.numwaterplanes = 0;
6477
6478         R_BlendView();
6479         if (r_timereport_active)
6480                 R_TimeReport("blendview");
6481
6482         GL_Scissor(0, 0, vid.width, vid.height);
6483         GL_ScissorTest(false);
6484
6485         r_refdef.view.matrix = originalmatrix;
6486
6487         CHECKGLERROR
6488 }
6489
6490 void R_RenderWaterPlanes(void)
6491 {
6492         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6493         {
6494                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6495                 if (r_timereport_active)
6496                         R_TimeReport("waterworld");
6497         }
6498
6499         // don't let sound skip if going slow
6500         if (r_refdef.scene.extraupdate)
6501                 S_ExtraUpdate ();
6502
6503         R_DrawModelsAddWaterPlanes();
6504         if (r_timereport_active)
6505                 R_TimeReport("watermodels");
6506
6507         if (r_waterstate.numwaterplanes)
6508         {
6509                 R_Water_ProcessPlanes();
6510                 if (r_timereport_active)
6511                         R_TimeReport("waterscenes");
6512         }
6513 }
6514
6515 extern void R_DrawLightningBeams (void);
6516 extern void VM_CL_AddPolygonsToMeshQueue (void);
6517 extern void R_DrawPortals (void);
6518 extern cvar_t cl_locs_show;
6519 static void R_DrawLocs(void);
6520 static void R_DrawEntityBBoxes(void);
6521 static void R_DrawModelDecals(void);
6522 extern void R_DrawModelShadows(void);
6523 extern void R_DrawModelShadowMaps(void);
6524 extern cvar_t cl_decals_newsystem;
6525 extern qboolean r_shadow_usingdeferredprepass;
6526 void R_RenderScene(void)
6527 {
6528         qboolean shadowmapping = false;
6529
6530         if (r_timereport_active)
6531                 R_TimeReport("beginscene");
6532
6533         r_refdef.stats.renders++;
6534
6535         R_UpdateFogColor();
6536
6537         // don't let sound skip if going slow
6538         if (r_refdef.scene.extraupdate)
6539                 S_ExtraUpdate ();
6540
6541         R_MeshQueue_BeginScene();
6542
6543         R_SkyStartFrame();
6544
6545         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);
6546
6547         if (r_timereport_active)
6548                 R_TimeReport("skystartframe");
6549
6550         if (cl.csqc_vidvars.drawworld)
6551         {
6552                 // don't let sound skip if going slow
6553                 if (r_refdef.scene.extraupdate)
6554                         S_ExtraUpdate ();
6555
6556                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6557                 {
6558                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6559                         if (r_timereport_active)
6560                                 R_TimeReport("worldsky");
6561                 }
6562
6563                 if (R_DrawBrushModelsSky() && r_timereport_active)
6564                         R_TimeReport("bmodelsky");
6565
6566                 if (skyrendermasked && skyrenderlater)
6567                 {
6568                         // we have to force off the water clipping plane while rendering sky
6569                         R_SetupView(false);
6570                         R_Sky();
6571                         R_SetupView(true);
6572                         if (r_timereport_active)
6573                                 R_TimeReport("sky");
6574                 }
6575         }
6576
6577         R_AnimCache_CacheVisibleEntities();
6578         if (r_timereport_active)
6579                 R_TimeReport("animation");
6580
6581         R_Shadow_PrepareLights();
6582         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6583                 R_Shadow_PrepareModelShadows();
6584         if (r_timereport_active)
6585                 R_TimeReport("preparelights");
6586
6587         if (R_Shadow_ShadowMappingEnabled())
6588                 shadowmapping = true;
6589
6590         if (r_shadow_usingdeferredprepass)
6591                 R_Shadow_DrawPrepass();
6592
6593         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6594         {
6595                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6596                 if (r_timereport_active)
6597                         R_TimeReport("worlddepth");
6598         }
6599         if (r_depthfirst.integer >= 2)
6600         {
6601                 R_DrawModelsDepth();
6602                 if (r_timereport_active)
6603                         R_TimeReport("modeldepth");
6604         }
6605
6606         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6607         {
6608                 R_DrawModelShadowMaps();
6609                 R_ResetViewRendering3D();
6610                 // don't let sound skip if going slow
6611                 if (r_refdef.scene.extraupdate)
6612                         S_ExtraUpdate ();
6613         }
6614
6615         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6616         {
6617                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6618                 if (r_timereport_active)
6619                         R_TimeReport("world");
6620         }
6621
6622         // don't let sound skip if going slow
6623         if (r_refdef.scene.extraupdate)
6624                 S_ExtraUpdate ();
6625
6626         R_DrawModels();
6627         if (r_timereport_active)
6628                 R_TimeReport("models");
6629
6630         // don't let sound skip if going slow
6631         if (r_refdef.scene.extraupdate)
6632                 S_ExtraUpdate ();
6633
6634         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6635         {
6636                 R_DrawModelShadows();
6637                 R_ResetViewRendering3D();
6638                 // don't let sound skip if going slow
6639                 if (r_refdef.scene.extraupdate)
6640                         S_ExtraUpdate ();
6641         }
6642
6643         if (!r_shadow_usingdeferredprepass)
6644         {
6645                 R_Shadow_DrawLights();
6646                 if (r_timereport_active)
6647                         R_TimeReport("rtlights");
6648         }
6649
6650         // don't let sound skip if going slow
6651         if (r_refdef.scene.extraupdate)
6652                 S_ExtraUpdate ();
6653
6654         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6655         {
6656                 R_DrawModelShadows();
6657                 R_ResetViewRendering3D();
6658                 // don't let sound skip if going slow
6659                 if (r_refdef.scene.extraupdate)
6660                         S_ExtraUpdate ();
6661         }
6662
6663         if (cl.csqc_vidvars.drawworld)
6664         {
6665                 if (cl_decals_newsystem.integer)
6666                 {
6667                         R_DrawModelDecals();
6668                         if (r_timereport_active)
6669                                 R_TimeReport("modeldecals");
6670                 }
6671                 else
6672                 {
6673                         R_DrawDecals();
6674                         if (r_timereport_active)
6675                                 R_TimeReport("decals");
6676                 }
6677
6678                 R_DrawParticles();
6679                 if (r_timereport_active)
6680                         R_TimeReport("particles");
6681
6682                 R_DrawExplosions();
6683                 if (r_timereport_active)
6684                         R_TimeReport("explosions");
6685
6686                 R_DrawLightningBeams();
6687                 if (r_timereport_active)
6688                         R_TimeReport("lightning");
6689         }
6690
6691         VM_CL_AddPolygonsToMeshQueue();
6692
6693         if (r_refdef.view.showdebug)
6694         {
6695                 if (cl_locs_show.integer)
6696                 {
6697                         R_DrawLocs();
6698                         if (r_timereport_active)
6699                                 R_TimeReport("showlocs");
6700                 }
6701
6702                 if (r_drawportals.integer)
6703                 {
6704                         R_DrawPortals();
6705                         if (r_timereport_active)
6706                                 R_TimeReport("portals");
6707                 }
6708
6709                 if (r_showbboxes.value > 0)
6710                 {
6711                         R_DrawEntityBBoxes();
6712                         if (r_timereport_active)
6713                                 R_TimeReport("bboxes");
6714                 }
6715         }
6716
6717         R_MeshQueue_RenderTransparent();
6718         if (r_timereport_active)
6719                 R_TimeReport("drawtrans");
6720
6721         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))
6722         {
6723                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6724                 if (r_timereport_active)
6725                         R_TimeReport("worlddebug");
6726                 R_DrawModelsDebug();
6727                 if (r_timereport_active)
6728                         R_TimeReport("modeldebug");
6729         }
6730
6731         if (cl.csqc_vidvars.drawworld)
6732         {
6733                 R_Shadow_DrawCoronas();
6734                 if (r_timereport_active)
6735                         R_TimeReport("coronas");
6736         }
6737
6738 #if 0
6739         {
6740                 GL_DepthTest(false);
6741                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6742                 GL_Color(1, 1, 1, 1);
6743                 qglBegin(GL_POLYGON);
6744                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6745                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6746                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6747                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6748                 qglEnd();
6749                 qglBegin(GL_POLYGON);
6750                 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]);
6751                 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]);
6752                 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]);
6753                 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]);
6754                 qglEnd();
6755                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6756         }
6757 #endif
6758
6759         // don't let sound skip if going slow
6760         if (r_refdef.scene.extraupdate)
6761                 S_ExtraUpdate ();
6762
6763         R_ResetViewRendering2D();
6764 }
6765
6766 static const unsigned short bboxelements[36] =
6767 {
6768         5, 1, 3, 5, 3, 7,
6769         6, 2, 0, 6, 0, 4,
6770         7, 3, 2, 7, 2, 6,
6771         4, 0, 1, 4, 1, 5,
6772         4, 5, 7, 4, 7, 6,
6773         1, 0, 2, 1, 2, 3,
6774 };
6775
6776 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6777 {
6778         int i;
6779         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6780
6781         RSurf_ActiveWorldEntity();
6782
6783         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6784         GL_DepthMask(false);
6785         GL_DepthRange(0, 1);
6786         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6787 //      R_Mesh_ResetTextureState();
6788
6789         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6790         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6791         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6792         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6793         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6794         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6795         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6796         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6797         R_FillColors(color4f, 8, cr, cg, cb, ca);
6798         if (r_refdef.fogenabled)
6799         {
6800                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6801                 {
6802                         f1 = RSurf_FogVertex(v);
6803                         f2 = 1 - f1;
6804                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6805                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6806                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6807                 }
6808         }
6809         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6810         R_Mesh_ResetTextureState();
6811         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6812         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6813 }
6814
6815 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6816 {
6817         int i;
6818         float color[4];
6819         prvm_edict_t *edict;
6820         prvm_prog_t *prog_save = prog;
6821
6822         // this function draws bounding boxes of server entities
6823         if (!sv.active)
6824                 return;
6825
6826         GL_CullFace(GL_NONE);
6827         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6828
6829         prog = 0;
6830         SV_VM_Begin();
6831         for (i = 0;i < numsurfaces;i++)
6832         {
6833                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6834                 switch ((int)edict->fields.server->solid)
6835                 {
6836                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6837                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6838                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6839                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6840                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6841                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6842                 }
6843                 color[3] *= r_showbboxes.value;
6844                 color[3] = bound(0, color[3], 1);
6845                 GL_DepthTest(!r_showdisabledepthtest.integer);
6846                 GL_CullFace(r_refdef.view.cullface_front);
6847                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6848         }
6849         SV_VM_End();
6850         prog = prog_save;
6851 }
6852
6853 static void R_DrawEntityBBoxes(void)
6854 {
6855         int i;
6856         prvm_edict_t *edict;
6857         vec3_t center;
6858         prvm_prog_t *prog_save = prog;
6859
6860         // this function draws bounding boxes of server entities
6861         if (!sv.active)
6862                 return;
6863
6864         prog = 0;
6865         SV_VM_Begin();
6866         for (i = 0;i < prog->num_edicts;i++)
6867         {
6868                 edict = PRVM_EDICT_NUM(i);
6869                 if (edict->priv.server->free)
6870                         continue;
6871                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6872                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6873                         continue;
6874                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6875                         continue;
6876                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6877                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6878         }
6879         SV_VM_End();
6880         prog = prog_save;
6881 }
6882
6883 static const int nomodelelement3i[24] =
6884 {
6885         5, 2, 0,
6886         5, 1, 2,
6887         5, 0, 3,
6888         5, 3, 1,
6889         0, 2, 4,
6890         2, 1, 4,
6891         3, 0, 4,
6892         1, 3, 4
6893 };
6894
6895 static const unsigned short nomodelelement3s[24] =
6896 {
6897         5, 2, 0,
6898         5, 1, 2,
6899         5, 0, 3,
6900         5, 3, 1,
6901         0, 2, 4,
6902         2, 1, 4,
6903         3, 0, 4,
6904         1, 3, 4
6905 };
6906
6907 static const float nomodelvertex3f[6*3] =
6908 {
6909         -16,   0,   0,
6910          16,   0,   0,
6911           0, -16,   0,
6912           0,  16,   0,
6913           0,   0, -16,
6914           0,   0,  16
6915 };
6916
6917 static const float nomodelcolor4f[6*4] =
6918 {
6919         0.0f, 0.0f, 0.5f, 1.0f,
6920         0.0f, 0.0f, 0.5f, 1.0f,
6921         0.0f, 0.5f, 0.0f, 1.0f,
6922         0.0f, 0.5f, 0.0f, 1.0f,
6923         0.5f, 0.0f, 0.0f, 1.0f,
6924         0.5f, 0.0f, 0.0f, 1.0f
6925 };
6926
6927 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6928 {
6929         int i;
6930         float f1, f2, *c;
6931         float color4f[6*4];
6932
6933         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);
6934
6935         // this is only called once per entity so numsurfaces is always 1, and
6936         // surfacelist is always {0}, so this code does not handle batches
6937
6938         if (rsurface.ent_flags & RENDER_ADDITIVE)
6939         {
6940                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6941                 GL_DepthMask(false);
6942         }
6943         else if (rsurface.colormod[3] < 1)
6944         {
6945                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6946                 GL_DepthMask(false);
6947         }
6948         else
6949         {
6950                 GL_BlendFunc(GL_ONE, GL_ZERO);
6951                 GL_DepthMask(true);
6952         }
6953         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6954         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6955         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6956         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6957         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6958         for (i = 0, c = color4f;i < 6;i++, c += 4)
6959         {
6960                 c[0] *= rsurface.colormod[0];
6961                 c[1] *= rsurface.colormod[1];
6962                 c[2] *= rsurface.colormod[2];
6963                 c[3] *= rsurface.colormod[3];
6964         }
6965         if (r_refdef.fogenabled)
6966         {
6967                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6968                 {
6969                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6970                         f2 = 1 - f1;
6971                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6972                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6973                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6974                 }
6975         }
6976 //      R_Mesh_ResetTextureState();
6977         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6978         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6979         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6980 }
6981
6982 void R_DrawNoModel(entity_render_t *ent)
6983 {
6984         vec3_t org;
6985         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6986         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6987                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6988         else
6989                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6990 }
6991
6992 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6993 {
6994         vec3_t right1, right2, diff, normal;
6995
6996         VectorSubtract (org2, org1, normal);
6997
6998         // calculate 'right' vector for start
6999         VectorSubtract (r_refdef.view.origin, org1, diff);
7000         CrossProduct (normal, diff, right1);
7001         VectorNormalize (right1);
7002
7003         // calculate 'right' vector for end
7004         VectorSubtract (r_refdef.view.origin, org2, diff);
7005         CrossProduct (normal, diff, right2);
7006         VectorNormalize (right2);
7007
7008         vert[ 0] = org1[0] + width * right1[0];
7009         vert[ 1] = org1[1] + width * right1[1];
7010         vert[ 2] = org1[2] + width * right1[2];
7011         vert[ 3] = org1[0] - width * right1[0];
7012         vert[ 4] = org1[1] - width * right1[1];
7013         vert[ 5] = org1[2] - width * right1[2];
7014         vert[ 6] = org2[0] - width * right2[0];
7015         vert[ 7] = org2[1] - width * right2[1];
7016         vert[ 8] = org2[2] - width * right2[2];
7017         vert[ 9] = org2[0] + width * right2[0];
7018         vert[10] = org2[1] + width * right2[1];
7019         vert[11] = org2[2] + width * right2[2];
7020 }
7021
7022 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)
7023 {
7024         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7025         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7026         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7027         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7028         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7029         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7030         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7031         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7032         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7033         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7034         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7035         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7036 }
7037
7038 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7039 {
7040         int i;
7041         float *vertex3f;
7042         float v[3];
7043         VectorSet(v, x, y, z);
7044         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7045                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7046                         break;
7047         if (i == mesh->numvertices)
7048         {
7049                 if (mesh->numvertices < mesh->maxvertices)
7050                 {
7051                         VectorCopy(v, vertex3f);
7052                         mesh->numvertices++;
7053                 }
7054                 return mesh->numvertices;
7055         }
7056         else
7057                 return i;
7058 }
7059
7060 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7061 {
7062         int i;
7063         int *e, element[3];
7064         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7065         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7066         e = mesh->element3i + mesh->numtriangles * 3;
7067         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7068         {
7069                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7070                 if (mesh->numtriangles < mesh->maxtriangles)
7071                 {
7072                         *e++ = element[0];
7073                         *e++ = element[1];
7074                         *e++ = element[2];
7075                         mesh->numtriangles++;
7076                 }
7077                 element[1] = element[2];
7078         }
7079 }
7080
7081 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7082 {
7083         int i;
7084         int *e, element[3];
7085         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7086         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7087         e = mesh->element3i + mesh->numtriangles * 3;
7088         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7089         {
7090                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7091                 if (mesh->numtriangles < mesh->maxtriangles)
7092                 {
7093                         *e++ = element[0];
7094                         *e++ = element[1];
7095                         *e++ = element[2];
7096                         mesh->numtriangles++;
7097                 }
7098                 element[1] = element[2];
7099         }
7100 }
7101
7102 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7103 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7104 {
7105         int planenum, planenum2;
7106         int w;
7107         int tempnumpoints;
7108         mplane_t *plane, *plane2;
7109         double maxdist;
7110         double temppoints[2][256*3];
7111         // figure out how large a bounding box we need to properly compute this brush
7112         maxdist = 0;
7113         for (w = 0;w < numplanes;w++)
7114                 maxdist = max(maxdist, fabs(planes[w].dist));
7115         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7116         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7117         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7118         {
7119                 w = 0;
7120                 tempnumpoints = 4;
7121                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7122                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7123                 {
7124                         if (planenum2 == planenum)
7125                                 continue;
7126                         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);
7127                         w = !w;
7128                 }
7129                 if (tempnumpoints < 3)
7130                         continue;
7131                 // generate elements forming a triangle fan for this polygon
7132                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7133         }
7134 }
7135
7136 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)
7137 {
7138         texturelayer_t *layer;
7139         layer = t->currentlayers + t->currentnumlayers++;
7140         layer->type = type;
7141         layer->depthmask = depthmask;
7142         layer->blendfunc1 = blendfunc1;
7143         layer->blendfunc2 = blendfunc2;
7144         layer->texture = texture;
7145         layer->texmatrix = *matrix;
7146         layer->color[0] = r;
7147         layer->color[1] = g;
7148         layer->color[2] = b;
7149         layer->color[3] = a;
7150 }
7151
7152 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7153 {
7154         if(parms[0] == 0 && parms[1] == 0)
7155                 return false;
7156         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7157                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7158                         return false;
7159         return true;
7160 }
7161
7162 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7163 {
7164         double index, f;
7165         index = parms[2] + r_refdef.scene.time * parms[3];
7166         index -= floor(index);
7167         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7168         {
7169         default:
7170         case Q3WAVEFUNC_NONE:
7171         case Q3WAVEFUNC_NOISE:
7172         case Q3WAVEFUNC_COUNT:
7173                 f = 0;
7174                 break;
7175         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7176         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7177         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7178         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7179         case Q3WAVEFUNC_TRIANGLE:
7180                 index *= 4;
7181                 f = index - floor(index);
7182                 if (index < 1)
7183                         f = f;
7184                 else if (index < 2)
7185                         f = 1 - f;
7186                 else if (index < 3)
7187                         f = -f;
7188                 else
7189                         f = -(1 - f);
7190                 break;
7191         }
7192         f = parms[0] + parms[1] * f;
7193         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7194                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7195         return (float) f;
7196 }
7197
7198 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7199 {
7200         int w, h, idx;
7201         float f;
7202         float tcmat[12];
7203         matrix4x4_t matrix, temp;
7204         switch(tcmod->tcmod)
7205         {
7206                 case Q3TCMOD_COUNT:
7207                 case Q3TCMOD_NONE:
7208                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7209                                 matrix = r_waterscrollmatrix;
7210                         else
7211                                 matrix = identitymatrix;
7212                         break;
7213                 case Q3TCMOD_ENTITYTRANSLATE:
7214                         // this is used in Q3 to allow the gamecode to control texcoord
7215                         // scrolling on the entity, which is not supported in darkplaces yet.
7216                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7217                         break;
7218                 case Q3TCMOD_ROTATE:
7219                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7220                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7221                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7222                         break;
7223                 case Q3TCMOD_SCALE:
7224                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7225                         break;
7226                 case Q3TCMOD_SCROLL:
7227                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7228                         break;
7229                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7230                         w = (int) tcmod->parms[0];
7231                         h = (int) tcmod->parms[1];
7232                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7233                         f = f - floor(f);
7234                         idx = (int) floor(f * w * h);
7235                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7236                         break;
7237                 case Q3TCMOD_STRETCH:
7238                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7239                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7240                         break;
7241                 case Q3TCMOD_TRANSFORM:
7242                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7243                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7244                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7245                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7246                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7247                         break;
7248                 case Q3TCMOD_TURBULENT:
7249                         // this is handled in the RSurf_PrepareVertices function
7250                         matrix = identitymatrix;
7251                         break;
7252         }
7253         temp = *texmatrix;
7254         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7255 }
7256
7257 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7258 {
7259         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7260         char name[MAX_QPATH];
7261         skinframe_t *skinframe;
7262         unsigned char pixels[296*194];
7263         strlcpy(cache->name, skinname, sizeof(cache->name));
7264         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7265         if (developer_loading.integer)
7266                 Con_Printf("loading %s\n", name);
7267         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7268         if (!skinframe || !skinframe->base)
7269         {
7270                 unsigned char *f;
7271                 fs_offset_t filesize;
7272                 skinframe = NULL;
7273                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7274                 if (f)
7275                 {
7276                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7277                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7278                         Mem_Free(f);
7279                 }
7280         }
7281         cache->skinframe = skinframe;
7282 }
7283
7284 texture_t *R_GetCurrentTexture(texture_t *t)
7285 {
7286         int i;
7287         const entity_render_t *ent = rsurface.entity;
7288         dp_model_t *model = ent->model;
7289         q3shaderinfo_layer_tcmod_t *tcmod;
7290
7291         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7292                 return t->currentframe;
7293         t->update_lastrenderframe = r_textureframe;
7294         t->update_lastrenderentity = (void *)ent;
7295
7296         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7297                 t->camera_entity = ent->entitynumber;
7298         else
7299                 t->camera_entity = 0;
7300
7301         // switch to an alternate material if this is a q1bsp animated material
7302         {
7303                 texture_t *texture = t;
7304                 int s = rsurface.ent_skinnum;
7305                 if ((unsigned int)s >= (unsigned int)model->numskins)
7306                         s = 0;
7307                 if (model->skinscenes)
7308                 {
7309                         if (model->skinscenes[s].framecount > 1)
7310                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7311                         else
7312                                 s = model->skinscenes[s].firstframe;
7313                 }
7314                 if (s > 0)
7315                         t = t + s * model->num_surfaces;
7316                 if (t->animated)
7317                 {
7318                         // use an alternate animation if the entity's frame is not 0,
7319                         // and only if the texture has an alternate animation
7320                         if (rsurface.ent_alttextures && t->anim_total[1])
7321                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7322                         else
7323                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7324                 }
7325                 texture->currentframe = t;
7326         }
7327
7328         // update currentskinframe to be a qw skin or animation frame
7329         if (rsurface.ent_qwskin >= 0)
7330         {
7331                 i = rsurface.ent_qwskin;
7332                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7333                 {
7334                         r_qwskincache_size = cl.maxclients;
7335                         if (r_qwskincache)
7336                                 Mem_Free(r_qwskincache);
7337                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7338                 }
7339                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7340                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7341                 t->currentskinframe = r_qwskincache[i].skinframe;
7342                 if (t->currentskinframe == NULL)
7343                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7344         }
7345         else if (t->numskinframes >= 2)
7346                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7347         if (t->backgroundnumskinframes >= 2)
7348                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7349
7350         t->currentmaterialflags = t->basematerialflags;
7351         t->currentalpha = rsurface.colormod[3];
7352         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7353                 t->currentalpha *= r_wateralpha.value;
7354         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7355                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7356         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7357                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7358         if (!(rsurface.ent_flags & RENDER_LIGHT))
7359                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7360         else if (FAKELIGHT_ENABLED)
7361         {
7362                         // no modellight if using fakelight for the map
7363         }
7364         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7365         {
7366                 // pick a model lighting mode
7367                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7368                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7369                 else
7370                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7371         }
7372         if (rsurface.ent_flags & RENDER_ADDITIVE)
7373                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7374         else if (t->currentalpha < 1)
7375                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7376         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7377                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7378         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7379                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7380         if (t->backgroundnumskinframes)
7381                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7382         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7383         {
7384                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7385                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7386         }
7387         else
7388                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7389         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7390                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7391
7392         // there is no tcmod
7393         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7394         {
7395                 t->currenttexmatrix = r_waterscrollmatrix;
7396                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7397         }
7398         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7399         {
7400                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7401                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7402         }
7403
7404         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7405                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7406         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7407                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7408
7409         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7410         if (t->currentskinframe->qpixels)
7411                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7412         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7413         if (!t->basetexture)
7414                 t->basetexture = r_texture_notexture;
7415         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7416         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7417         t->nmaptexture = t->currentskinframe->nmap;
7418         if (!t->nmaptexture)
7419                 t->nmaptexture = r_texture_blanknormalmap;
7420         t->glosstexture = r_texture_black;
7421         t->glowtexture = t->currentskinframe->glow;
7422         t->fogtexture = t->currentskinframe->fog;
7423         t->reflectmasktexture = t->currentskinframe->reflect;
7424         if (t->backgroundnumskinframes)
7425         {
7426                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7427                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7428                 t->backgroundglosstexture = r_texture_black;
7429                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7430                 if (!t->backgroundnmaptexture)
7431                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7432         }
7433         else
7434         {
7435                 t->backgroundbasetexture = r_texture_white;
7436                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7437                 t->backgroundglosstexture = r_texture_black;
7438                 t->backgroundglowtexture = NULL;
7439         }
7440         t->specularpower = r_shadow_glossexponent.value;
7441         // TODO: store reference values for these in the texture?
7442         t->specularscale = 0;
7443         if (r_shadow_gloss.integer > 0)
7444         {
7445                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7446                 {
7447                         if (r_shadow_glossintensity.value > 0)
7448                         {
7449                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7450                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7451                                 t->specularscale = r_shadow_glossintensity.value;
7452                         }
7453                 }
7454                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7455                 {
7456                         t->glosstexture = r_texture_white;
7457                         t->backgroundglosstexture = r_texture_white;
7458                         t->specularscale = r_shadow_gloss2intensity.value;
7459                         t->specularpower = r_shadow_gloss2exponent.value;
7460                 }
7461         }
7462         t->specularscale *= t->specularscalemod;
7463         t->specularpower *= t->specularpowermod;
7464
7465         // lightmaps mode looks bad with dlights using actual texturing, so turn
7466         // off the colormap and glossmap, but leave the normalmap on as it still
7467         // accurately represents the shading involved
7468         if (gl_lightmaps.integer)
7469         {
7470                 t->basetexture = r_texture_grey128;
7471                 t->pantstexture = r_texture_black;
7472                 t->shirttexture = r_texture_black;
7473                 t->nmaptexture = r_texture_blanknormalmap;
7474                 t->glosstexture = r_texture_black;
7475                 t->glowtexture = NULL;
7476                 t->fogtexture = NULL;
7477                 t->reflectmasktexture = NULL;
7478                 t->backgroundbasetexture = NULL;
7479                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7480                 t->backgroundglosstexture = r_texture_black;
7481                 t->backgroundglowtexture = NULL;
7482                 t->specularscale = 0;
7483                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7484         }
7485
7486         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7487         VectorClear(t->dlightcolor);
7488         t->currentnumlayers = 0;
7489         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7490         {
7491                 int blendfunc1, blendfunc2;
7492                 qboolean depthmask;
7493                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7494                 {
7495                         blendfunc1 = GL_SRC_ALPHA;
7496                         blendfunc2 = GL_ONE;
7497                 }
7498                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7499                 {
7500                         blendfunc1 = GL_SRC_ALPHA;
7501                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7502                 }
7503                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7504                 {
7505                         blendfunc1 = t->customblendfunc[0];
7506                         blendfunc2 = t->customblendfunc[1];
7507                 }
7508                 else
7509                 {
7510                         blendfunc1 = GL_ONE;
7511                         blendfunc2 = GL_ZERO;
7512                 }
7513                 // don't colormod evilblend textures
7514                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7515                         VectorSet(t->lightmapcolor, 1, 1, 1);
7516                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7517                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7518                 {
7519                         // fullbright is not affected by r_refdef.lightmapintensity
7520                         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]);
7521                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7522                                 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]);
7523                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7524                                 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]);
7525                 }
7526                 else
7527                 {
7528                         vec3_t ambientcolor;
7529                         float colorscale;
7530                         // set the color tint used for lights affecting this surface
7531                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7532                         colorscale = 2;
7533                         // q3bsp has no lightmap updates, so the lightstylevalue that
7534                         // would normally be baked into the lightmap must be
7535                         // applied to the color
7536                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7537                         if (model->type == mod_brushq3)
7538                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7539                         colorscale *= r_refdef.lightmapintensity;
7540                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7541                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7542                         // basic lit geometry
7543                         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]);
7544                         // add pants/shirt if needed
7545                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7546                                 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]);
7547                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7548                                 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]);
7549                         // now add ambient passes if needed
7550                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7551                         {
7552                                 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]);
7553                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7554                                         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]);
7555                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7556                                         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]);
7557                         }
7558                 }
7559                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7560                         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]);
7561                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7562                 {
7563                         // if this is opaque use alpha blend which will darken the earlier
7564                         // passes cheaply.
7565                         //
7566                         // if this is an alpha blended material, all the earlier passes
7567                         // were darkened by fog already, so we only need to add the fog
7568                         // color ontop through the fog mask texture
7569                         //
7570                         // if this is an additive blended material, all the earlier passes
7571                         // were darkened by fog already, and we should not add fog color
7572                         // (because the background was not darkened, there is no fog color
7573                         // that was lost behind it).
7574                         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]);
7575                 }
7576         }
7577
7578         return t->currentframe;
7579 }
7580
7581 rsurfacestate_t rsurface;
7582
7583 void RSurf_ActiveWorldEntity(void)
7584 {
7585         dp_model_t *model = r_refdef.scene.worldmodel;
7586         //if (rsurface.entity == r_refdef.scene.worldentity)
7587         //      return;
7588         rsurface.entity = r_refdef.scene.worldentity;
7589         rsurface.skeleton = NULL;
7590         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7591         rsurface.ent_skinnum = 0;
7592         rsurface.ent_qwskin = -1;
7593         rsurface.ent_shadertime = 0;
7594         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7595         rsurface.matrix = identitymatrix;
7596         rsurface.inversematrix = identitymatrix;
7597         rsurface.matrixscale = 1;
7598         rsurface.inversematrixscale = 1;
7599         R_EntityMatrix(&identitymatrix);
7600         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7601         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7602         rsurface.fograngerecip = r_refdef.fograngerecip;
7603         rsurface.fogheightfade = r_refdef.fogheightfade;
7604         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7605         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7606         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7607         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7608         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7609         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7610         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7611         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7612         rsurface.colormod[3] = 1;
7613         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);
7614         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7615         rsurface.frameblend[0].lerp = 1;
7616         rsurface.ent_alttextures = false;
7617         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7618         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7619         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7620         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7621         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7622         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7623         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7624         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7625         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7626         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7627         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7628         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7629         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7630         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7631         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7632         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7633         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7634         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7635         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7636         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7637         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7638         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7639         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7640         rsurface.modelelement3i = model->surfmesh.data_element3i;
7641         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7642         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7643         rsurface.modelelement3s = model->surfmesh.data_element3s;
7644         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7645         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7646         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7647         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7648         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7649         rsurface.modelsurfaces = model->data_surfaces;
7650         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7651         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7652         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7653         rsurface.modelgeneratedvertex = false;
7654         rsurface.batchgeneratedvertex = false;
7655         rsurface.batchfirstvertex = 0;
7656         rsurface.batchnumvertices = 0;
7657         rsurface.batchfirsttriangle = 0;
7658         rsurface.batchnumtriangles = 0;
7659         rsurface.batchvertex3f  = NULL;
7660         rsurface.batchvertex3f_vertexbuffer = NULL;
7661         rsurface.batchvertex3f_bufferoffset = 0;
7662         rsurface.batchsvector3f = NULL;
7663         rsurface.batchsvector3f_vertexbuffer = NULL;
7664         rsurface.batchsvector3f_bufferoffset = 0;
7665         rsurface.batchtvector3f = NULL;
7666         rsurface.batchtvector3f_vertexbuffer = NULL;
7667         rsurface.batchtvector3f_bufferoffset = 0;
7668         rsurface.batchnormal3f  = NULL;
7669         rsurface.batchnormal3f_vertexbuffer = NULL;
7670         rsurface.batchnormal3f_bufferoffset = 0;
7671         rsurface.batchlightmapcolor4f = NULL;
7672         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7673         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7674         rsurface.batchtexcoordtexture2f = NULL;
7675         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7676         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7677         rsurface.batchtexcoordlightmap2f = NULL;
7678         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7679         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7680         rsurface.batchvertexmesh = NULL;
7681         rsurface.batchvertexmeshbuffer = NULL;
7682         rsurface.batchvertex3fbuffer = NULL;
7683         rsurface.batchelement3i = NULL;
7684         rsurface.batchelement3i_indexbuffer = NULL;
7685         rsurface.batchelement3i_bufferoffset = 0;
7686         rsurface.batchelement3s = NULL;
7687         rsurface.batchelement3s_indexbuffer = NULL;
7688         rsurface.batchelement3s_bufferoffset = 0;
7689         rsurface.passcolor4f = NULL;
7690         rsurface.passcolor4f_vertexbuffer = NULL;
7691         rsurface.passcolor4f_bufferoffset = 0;
7692 }
7693
7694 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7695 {
7696         dp_model_t *model = ent->model;
7697         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7698         //      return;
7699         rsurface.entity = (entity_render_t *)ent;
7700         rsurface.skeleton = ent->skeleton;
7701         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7702         rsurface.ent_skinnum = ent->skinnum;
7703         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;
7704         rsurface.ent_shadertime = ent->shadertime;
7705         rsurface.ent_flags = ent->flags;
7706         rsurface.matrix = ent->matrix;
7707         rsurface.inversematrix = ent->inversematrix;
7708         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7709         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7710         R_EntityMatrix(&rsurface.matrix);
7711         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7712         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7713         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7714         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7715         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7716         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7717         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7718         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7719         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7720         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7721         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7722         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7723         rsurface.colormod[3] = ent->alpha;
7724         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7725         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7726         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7727         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7728         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7729         if (ent->model->brush.submodel && !prepass)
7730         {
7731                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7732                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7733         }
7734         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7735         {
7736                 if (ent->animcache_vertex3f)
7737                 {
7738                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7739                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7740                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7741                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7742                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7743                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7744                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7745                 }
7746                 else if (wanttangents)
7747                 {
7748                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7749                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7750                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7751                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7752                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7753                         rsurface.modelvertexmesh = NULL;
7754                         rsurface.modelvertexmeshbuffer = NULL;
7755                         rsurface.modelvertex3fbuffer = NULL;
7756                 }
7757                 else if (wantnormals)
7758                 {
7759                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7760                         rsurface.modelsvector3f = NULL;
7761                         rsurface.modeltvector3f = NULL;
7762                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7763                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7764                         rsurface.modelvertexmesh = NULL;
7765                         rsurface.modelvertexmeshbuffer = NULL;
7766                         rsurface.modelvertex3fbuffer = NULL;
7767                 }
7768                 else
7769                 {
7770                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7771                         rsurface.modelsvector3f = NULL;
7772                         rsurface.modeltvector3f = NULL;
7773                         rsurface.modelnormal3f = NULL;
7774                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7775                         rsurface.modelvertexmesh = NULL;
7776                         rsurface.modelvertexmeshbuffer = NULL;
7777                         rsurface.modelvertex3fbuffer = NULL;
7778                 }
7779                 rsurface.modelvertex3f_vertexbuffer = 0;
7780                 rsurface.modelvertex3f_bufferoffset = 0;
7781                 rsurface.modelsvector3f_vertexbuffer = 0;
7782                 rsurface.modelsvector3f_bufferoffset = 0;
7783                 rsurface.modeltvector3f_vertexbuffer = 0;
7784                 rsurface.modeltvector3f_bufferoffset = 0;
7785                 rsurface.modelnormal3f_vertexbuffer = 0;
7786                 rsurface.modelnormal3f_bufferoffset = 0;
7787                 rsurface.modelgeneratedvertex = true;
7788         }
7789         else
7790         {
7791                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7792                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7793                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7794                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7795                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7796                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7797                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7798                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7799                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7800                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7801                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7802                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7803                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7804                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7805                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7806                 rsurface.modelgeneratedvertex = false;
7807         }
7808         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7809         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7810         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7811         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7812         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7813         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7814         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7815         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7816         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7817         rsurface.modelelement3i = model->surfmesh.data_element3i;
7818         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7819         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7820         rsurface.modelelement3s = model->surfmesh.data_element3s;
7821         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7822         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7823         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7824         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7825         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7826         rsurface.modelsurfaces = model->data_surfaces;
7827         rsurface.batchgeneratedvertex = false;
7828         rsurface.batchfirstvertex = 0;
7829         rsurface.batchnumvertices = 0;
7830         rsurface.batchfirsttriangle = 0;
7831         rsurface.batchnumtriangles = 0;
7832         rsurface.batchvertex3f  = NULL;
7833         rsurface.batchvertex3f_vertexbuffer = NULL;
7834         rsurface.batchvertex3f_bufferoffset = 0;
7835         rsurface.batchsvector3f = NULL;
7836         rsurface.batchsvector3f_vertexbuffer = NULL;
7837         rsurface.batchsvector3f_bufferoffset = 0;
7838         rsurface.batchtvector3f = NULL;
7839         rsurface.batchtvector3f_vertexbuffer = NULL;
7840         rsurface.batchtvector3f_bufferoffset = 0;
7841         rsurface.batchnormal3f  = NULL;
7842         rsurface.batchnormal3f_vertexbuffer = NULL;
7843         rsurface.batchnormal3f_bufferoffset = 0;
7844         rsurface.batchlightmapcolor4f = NULL;
7845         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7846         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7847         rsurface.batchtexcoordtexture2f = NULL;
7848         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7849         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7850         rsurface.batchtexcoordlightmap2f = NULL;
7851         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7852         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7853         rsurface.batchvertexmesh = NULL;
7854         rsurface.batchvertexmeshbuffer = NULL;
7855         rsurface.batchvertex3fbuffer = NULL;
7856         rsurface.batchelement3i = NULL;
7857         rsurface.batchelement3i_indexbuffer = NULL;
7858         rsurface.batchelement3i_bufferoffset = 0;
7859         rsurface.batchelement3s = NULL;
7860         rsurface.batchelement3s_indexbuffer = NULL;
7861         rsurface.batchelement3s_bufferoffset = 0;
7862         rsurface.passcolor4f = NULL;
7863         rsurface.passcolor4f_vertexbuffer = NULL;
7864         rsurface.passcolor4f_bufferoffset = 0;
7865 }
7866
7867 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)
7868 {
7869         rsurface.entity = r_refdef.scene.worldentity;
7870         rsurface.skeleton = NULL;
7871         rsurface.ent_skinnum = 0;
7872         rsurface.ent_qwskin = -1;
7873         rsurface.ent_shadertime = shadertime;
7874         rsurface.ent_flags = entflags;
7875         rsurface.modelnumvertices = numvertices;
7876         rsurface.modelnumtriangles = numtriangles;
7877         rsurface.matrix = *matrix;
7878         rsurface.inversematrix = *inversematrix;
7879         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7880         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7881         R_EntityMatrix(&rsurface.matrix);
7882         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7883         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7884         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7885         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7886         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7887         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7888         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7889         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7890         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7891         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7892         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7893         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7894         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);
7895         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7896         rsurface.frameblend[0].lerp = 1;
7897         rsurface.ent_alttextures = false;
7898         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7899         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7900         if (wanttangents)
7901         {
7902                 rsurface.modelvertex3f = (float *)vertex3f;
7903                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7904                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7905                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7906         }
7907         else if (wantnormals)
7908         {
7909                 rsurface.modelvertex3f = (float *)vertex3f;
7910                 rsurface.modelsvector3f = NULL;
7911                 rsurface.modeltvector3f = NULL;
7912                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7913         }
7914         else
7915         {
7916                 rsurface.modelvertex3f = (float *)vertex3f;
7917                 rsurface.modelsvector3f = NULL;
7918                 rsurface.modeltvector3f = NULL;
7919                 rsurface.modelnormal3f = NULL;
7920         }
7921         rsurface.modelvertexmesh = NULL;
7922         rsurface.modelvertexmeshbuffer = NULL;
7923         rsurface.modelvertex3fbuffer = NULL;
7924         rsurface.modelvertex3f_vertexbuffer = 0;
7925         rsurface.modelvertex3f_bufferoffset = 0;
7926         rsurface.modelsvector3f_vertexbuffer = 0;
7927         rsurface.modelsvector3f_bufferoffset = 0;
7928         rsurface.modeltvector3f_vertexbuffer = 0;
7929         rsurface.modeltvector3f_bufferoffset = 0;
7930         rsurface.modelnormal3f_vertexbuffer = 0;
7931         rsurface.modelnormal3f_bufferoffset = 0;
7932         rsurface.modelgeneratedvertex = true;
7933         rsurface.modellightmapcolor4f  = (float *)color4f;
7934         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7935         rsurface.modellightmapcolor4f_bufferoffset = 0;
7936         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7937         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7938         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7939         rsurface.modeltexcoordlightmap2f  = NULL;
7940         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7941         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7942         rsurface.modelelement3i = (int *)element3i;
7943         rsurface.modelelement3i_indexbuffer = NULL;
7944         rsurface.modelelement3i_bufferoffset = 0;
7945         rsurface.modelelement3s = (unsigned short *)element3s;
7946         rsurface.modelelement3s_indexbuffer = NULL;
7947         rsurface.modelelement3s_bufferoffset = 0;
7948         rsurface.modellightmapoffsets = NULL;
7949         rsurface.modelsurfaces = NULL;
7950         rsurface.batchgeneratedvertex = false;
7951         rsurface.batchfirstvertex = 0;
7952         rsurface.batchnumvertices = 0;
7953         rsurface.batchfirsttriangle = 0;
7954         rsurface.batchnumtriangles = 0;
7955         rsurface.batchvertex3f  = NULL;
7956         rsurface.batchvertex3f_vertexbuffer = NULL;
7957         rsurface.batchvertex3f_bufferoffset = 0;
7958         rsurface.batchsvector3f = NULL;
7959         rsurface.batchsvector3f_vertexbuffer = NULL;
7960         rsurface.batchsvector3f_bufferoffset = 0;
7961         rsurface.batchtvector3f = NULL;
7962         rsurface.batchtvector3f_vertexbuffer = NULL;
7963         rsurface.batchtvector3f_bufferoffset = 0;
7964         rsurface.batchnormal3f  = NULL;
7965         rsurface.batchnormal3f_vertexbuffer = NULL;
7966         rsurface.batchnormal3f_bufferoffset = 0;
7967         rsurface.batchlightmapcolor4f = NULL;
7968         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7969         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7970         rsurface.batchtexcoordtexture2f = NULL;
7971         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7972         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7973         rsurface.batchtexcoordlightmap2f = NULL;
7974         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7975         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7976         rsurface.batchvertexmesh = NULL;
7977         rsurface.batchvertexmeshbuffer = NULL;
7978         rsurface.batchvertex3fbuffer = NULL;
7979         rsurface.batchelement3i = NULL;
7980         rsurface.batchelement3i_indexbuffer = NULL;
7981         rsurface.batchelement3i_bufferoffset = 0;
7982         rsurface.batchelement3s = NULL;
7983         rsurface.batchelement3s_indexbuffer = NULL;
7984         rsurface.batchelement3s_bufferoffset = 0;
7985         rsurface.passcolor4f = NULL;
7986         rsurface.passcolor4f_vertexbuffer = NULL;
7987         rsurface.passcolor4f_bufferoffset = 0;
7988
7989         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7990         {
7991                 if ((wantnormals || wanttangents) && !normal3f)
7992                 {
7993                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7994                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7995                 }
7996                 if (wanttangents && !svector3f)
7997                 {
7998                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7999                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8000                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8001                 }
8002         }
8003 }
8004
8005 float RSurf_FogPoint(const float *v)
8006 {
8007         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8008         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8009         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8010         float FogHeightFade = r_refdef.fogheightfade;
8011         float fogfrac;
8012         unsigned int fogmasktableindex;
8013         if (r_refdef.fogplaneviewabove)
8014                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8015         else
8016                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8017         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8018         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8019 }
8020
8021 float RSurf_FogVertex(const float *v)
8022 {
8023         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8024         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8025         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8026         float FogHeightFade = rsurface.fogheightfade;
8027         float fogfrac;
8028         unsigned int fogmasktableindex;
8029         if (r_refdef.fogplaneviewabove)
8030                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8031         else
8032                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8033         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8034         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8035 }
8036
8037 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8038 {
8039         int i;
8040         for (i = 0;i < numelements;i++)
8041                 outelement3i[i] = inelement3i[i] + adjust;
8042 }
8043
8044 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8045 extern cvar_t gl_vbo;
8046 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8047 {
8048         int deformindex;
8049         int firsttriangle;
8050         int numtriangles;
8051         int firstvertex;
8052         int endvertex;
8053         int numvertices;
8054         int surfacefirsttriangle;
8055         int surfacenumtriangles;
8056         int surfacefirstvertex;
8057         int surfaceendvertex;
8058         int surfacenumvertices;
8059         int batchnumvertices;
8060         int batchnumtriangles;
8061         int needsupdate;
8062         int i, j;
8063         qboolean gaps;
8064         qboolean dynamicvertex;
8065         float amplitude;
8066         float animpos;
8067         float scale;
8068         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8069         float waveparms[4];
8070         q3shaderinfo_deform_t *deform;
8071         const msurface_t *surface, *firstsurface;
8072         r_vertexmesh_t *vertexmesh;
8073         if (!texturenumsurfaces)
8074                 return;
8075         // find vertex range of this surface batch
8076         gaps = false;
8077         firstsurface = texturesurfacelist[0];
8078         firsttriangle = firstsurface->num_firsttriangle;
8079         batchnumvertices = 0;
8080         batchnumtriangles = 0;
8081         firstvertex = endvertex = firstsurface->num_firstvertex;
8082         for (i = 0;i < texturenumsurfaces;i++)
8083         {
8084                 surface = texturesurfacelist[i];
8085                 if (surface != firstsurface + i)
8086                         gaps = true;
8087                 surfacefirstvertex = surface->num_firstvertex;
8088                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8089                 surfacenumvertices = surface->num_vertices;
8090                 surfacenumtriangles = surface->num_triangles;
8091                 if (firstvertex > surfacefirstvertex)
8092                         firstvertex = surfacefirstvertex;
8093                 if (endvertex < surfaceendvertex)
8094                         endvertex = surfaceendvertex;
8095                 batchnumvertices += surfacenumvertices;
8096                 batchnumtriangles += surfacenumtriangles;
8097         }
8098
8099         // we now know the vertex range used, and if there are any gaps in it
8100         rsurface.batchfirstvertex = firstvertex;
8101         rsurface.batchnumvertices = endvertex - firstvertex;
8102         rsurface.batchfirsttriangle = firsttriangle;
8103         rsurface.batchnumtriangles = batchnumtriangles;
8104
8105         // this variable holds flags for which properties have been updated that
8106         // may require regenerating vertexmesh array...
8107         needsupdate = 0;
8108
8109         // check if any dynamic vertex processing must occur
8110         dynamicvertex = false;
8111
8112         // if there is a chance of animated vertex colors, it's a dynamic batch
8113         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8114         {
8115                 dynamicvertex = true;
8116                 batchneed |= BATCHNEED_NOGAPS;
8117                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8118         }
8119
8120         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8121         {
8122                 switch (deform->deform)
8123                 {
8124                 default:
8125                 case Q3DEFORM_PROJECTIONSHADOW:
8126                 case Q3DEFORM_TEXT0:
8127                 case Q3DEFORM_TEXT1:
8128                 case Q3DEFORM_TEXT2:
8129                 case Q3DEFORM_TEXT3:
8130                 case Q3DEFORM_TEXT4:
8131                 case Q3DEFORM_TEXT5:
8132                 case Q3DEFORM_TEXT6:
8133                 case Q3DEFORM_TEXT7:
8134                 case Q3DEFORM_NONE:
8135                         break;
8136                 case Q3DEFORM_AUTOSPRITE:
8137                         dynamicvertex = true;
8138                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8139                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8140                         break;
8141                 case Q3DEFORM_AUTOSPRITE2:
8142                         dynamicvertex = true;
8143                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8144                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8145                         break;
8146                 case Q3DEFORM_NORMAL:
8147                         dynamicvertex = true;
8148                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8149                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8150                         break;
8151                 case Q3DEFORM_WAVE:
8152                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8153                                 break; // if wavefunc is a nop, ignore this transform
8154                         dynamicvertex = true;
8155                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8156                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8157                         break;
8158                 case Q3DEFORM_BULGE:
8159                         dynamicvertex = true;
8160                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8161                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8162                         break;
8163                 case Q3DEFORM_MOVE:
8164                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8165                                 break; // if wavefunc is a nop, ignore this transform
8166                         dynamicvertex = true;
8167                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8168                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8169                         break;
8170                 }
8171         }
8172         switch(rsurface.texture->tcgen.tcgen)
8173         {
8174         default:
8175         case Q3TCGEN_TEXTURE:
8176                 break;
8177         case Q3TCGEN_LIGHTMAP:
8178                 dynamicvertex = true;
8179                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8180                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8181                 break;
8182         case Q3TCGEN_VECTOR:
8183                 dynamicvertex = true;
8184                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8185                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8186                 break;
8187         case Q3TCGEN_ENVIRONMENT:
8188                 dynamicvertex = true;
8189                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8190                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8191                 break;
8192         }
8193         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8194         {
8195                 dynamicvertex = true;
8196                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8197                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8198         }
8199
8200         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8201         {
8202                 dynamicvertex = true;
8203                 batchneed |= BATCHNEED_NOGAPS;
8204                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8205         }
8206
8207         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8208         {
8209                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8210                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8211                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8212                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8213                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8214                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8215                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8216         }
8217
8218         // when the model data has no vertex buffer (dynamic mesh), we need to
8219         // eliminate gaps
8220         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8221                 batchneed |= BATCHNEED_NOGAPS;
8222
8223         // if needsupdate, we have to do a dynamic vertex batch for sure
8224         if (needsupdate & batchneed)
8225                 dynamicvertex = true;
8226
8227         // see if we need to build vertexmesh from arrays
8228         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8229                 dynamicvertex = true;
8230
8231         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8232         // also some drivers strongly dislike firstvertex
8233         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8234                 dynamicvertex = true;
8235
8236         rsurface.batchvertex3f = rsurface.modelvertex3f;
8237         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8238         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8239         rsurface.batchsvector3f = rsurface.modelsvector3f;
8240         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8241         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8242         rsurface.batchtvector3f = rsurface.modeltvector3f;
8243         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8244         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8245         rsurface.batchnormal3f = rsurface.modelnormal3f;
8246         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8247         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8248         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8249         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8250         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8251         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8252         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8253         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8254         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8255         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8256         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8257         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8258         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8259         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8260         rsurface.batchelement3i = rsurface.modelelement3i;
8261         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8262         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8263         rsurface.batchelement3s = rsurface.modelelement3s;
8264         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8265         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8266
8267         // if any dynamic vertex processing has to occur in software, we copy the
8268         // entire surface list together before processing to rebase the vertices
8269         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8270         //
8271         // if any gaps exist and we do not have a static vertex buffer, we have to
8272         // copy the surface list together to avoid wasting upload bandwidth on the
8273         // vertices in the gaps.
8274         //
8275         // if gaps exist and we have a static vertex buffer, we still have to
8276         // combine the index buffer ranges into one dynamic index buffer.
8277         //
8278         // in all cases we end up with data that can be drawn in one call.
8279
8280         if (!dynamicvertex)
8281         {
8282                 // static vertex data, just set pointers...
8283                 rsurface.batchgeneratedvertex = false;
8284                 // if there are gaps, we want to build a combined index buffer,
8285                 // otherwise use the original static buffer with an appropriate offset
8286                 if (gaps)
8287                 {
8288                         // build a new triangle elements array for this batch
8289                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8290                         rsurface.batchfirsttriangle = 0;
8291                         numtriangles = 0;
8292                         for (i = 0;i < texturenumsurfaces;i++)
8293                         {
8294                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8295                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8296                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8297                                 numtriangles += surfacenumtriangles;
8298                         }
8299                         rsurface.batchelement3i_indexbuffer = NULL;
8300                         rsurface.batchelement3i_bufferoffset = 0;
8301                         rsurface.batchelement3s = NULL;
8302                         rsurface.batchelement3s_indexbuffer = NULL;
8303                         rsurface.batchelement3s_bufferoffset = 0;
8304                         if (endvertex <= 65536)
8305                         {
8306                                 // make a 16bit (unsigned short) index array if possible
8307                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8308                                 for (i = 0;i < numtriangles*3;i++)
8309                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8310                         }
8311                 }
8312                 return;
8313         }
8314
8315         // something needs software processing, do it for real...
8316         // we only directly handle separate array data in this case and then
8317         // generate interleaved data if needed...
8318         rsurface.batchgeneratedvertex = true;
8319
8320         // now copy the vertex data into a combined array and make an index array
8321         // (this is what Quake3 does all the time)
8322         //if (gaps || rsurface.batchfirstvertex)
8323         {
8324                 rsurface.batchvertex3fbuffer = NULL;
8325                 rsurface.batchvertexmesh = NULL;
8326                 rsurface.batchvertexmeshbuffer = NULL;
8327                 rsurface.batchvertex3f = NULL;
8328                 rsurface.batchvertex3f_vertexbuffer = NULL;
8329                 rsurface.batchvertex3f_bufferoffset = 0;
8330                 rsurface.batchsvector3f = NULL;
8331                 rsurface.batchsvector3f_vertexbuffer = NULL;
8332                 rsurface.batchsvector3f_bufferoffset = 0;
8333                 rsurface.batchtvector3f = NULL;
8334                 rsurface.batchtvector3f_vertexbuffer = NULL;
8335                 rsurface.batchtvector3f_bufferoffset = 0;
8336                 rsurface.batchnormal3f = NULL;
8337                 rsurface.batchnormal3f_vertexbuffer = NULL;
8338                 rsurface.batchnormal3f_bufferoffset = 0;
8339                 rsurface.batchlightmapcolor4f = NULL;
8340                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8341                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8342                 rsurface.batchtexcoordtexture2f = NULL;
8343                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8344                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8345                 rsurface.batchtexcoordlightmap2f = NULL;
8346                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8347                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8348                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8349                 rsurface.batchelement3i_indexbuffer = NULL;
8350                 rsurface.batchelement3i_bufferoffset = 0;
8351                 rsurface.batchelement3s = NULL;
8352                 rsurface.batchelement3s_indexbuffer = NULL;
8353                 rsurface.batchelement3s_bufferoffset = 0;
8354                 // we'll only be setting up certain arrays as needed
8355                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8356                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8357                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8358                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8359                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8360                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8361                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8362                 {
8363                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8364                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8365                 }
8366                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8367                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8368                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8369                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8370                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8371                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8372                 numvertices = 0;
8373                 numtriangles = 0;
8374                 for (i = 0;i < texturenumsurfaces;i++)
8375                 {
8376                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8377                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8378                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8379                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8380                         // copy only the data requested
8381                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8382                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8383                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8384                         {
8385                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8386                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8387                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8388                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8389                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8390                                 {
8391                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8392                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8393                                 }
8394                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8395                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8396                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8397                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8398                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8399                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8400                         }
8401                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8402                         numvertices += surfacenumvertices;
8403                         numtriangles += surfacenumtriangles;
8404                 }
8405
8406                 // generate a 16bit index array as well if possible
8407                 // (in general, dynamic batches fit)
8408                 if (numvertices <= 65536)
8409                 {
8410                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8411                         for (i = 0;i < numtriangles*3;i++)
8412                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8413                 }
8414
8415                 // since we've copied everything, the batch now starts at 0
8416                 rsurface.batchfirstvertex = 0;
8417                 rsurface.batchnumvertices = batchnumvertices;
8418                 rsurface.batchfirsttriangle = 0;
8419                 rsurface.batchnumtriangles = batchnumtriangles;
8420         }
8421
8422         // q1bsp surfaces rendered in vertex color mode have to have colors
8423         // calculated based on lightstyles
8424         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8425         {
8426                 // generate color arrays for the surfaces in this list
8427                 int c[4];
8428                 int scale;
8429                 int size3;
8430                 const int *offsets;
8431                 const unsigned char *lm;
8432                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8433                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8434                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8435                 numvertices = 0;
8436                 for (i = 0;i < texturenumsurfaces;i++)
8437                 {
8438                         surface = texturesurfacelist[i];
8439                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8440                         surfacenumvertices = surface->num_vertices;
8441                         if (surface->lightmapinfo->samples)
8442                         {
8443                                 for (j = 0;j < surfacenumvertices;j++)
8444                                 {
8445                                         lm = surface->lightmapinfo->samples + offsets[j];
8446                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8447                                         VectorScale(lm, scale, c);
8448                                         if (surface->lightmapinfo->styles[1] != 255)
8449                                         {
8450                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8451                                                 lm += size3;
8452                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8453                                                 VectorMA(c, scale, lm, c);
8454                                                 if (surface->lightmapinfo->styles[2] != 255)
8455                                                 {
8456                                                         lm += size3;
8457                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8458                                                         VectorMA(c, scale, lm, c);
8459                                                         if (surface->lightmapinfo->styles[3] != 255)
8460                                                         {
8461                                                                 lm += size3;
8462                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8463                                                                 VectorMA(c, scale, lm, c);
8464                                                         }
8465                                                 }
8466                                         }
8467                                         c[0] >>= 7;
8468                                         c[1] >>= 7;
8469                                         c[2] >>= 7;
8470                                         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);
8471                                         numvertices++;
8472                                 }
8473                         }
8474                         else
8475                         {
8476                                 for (j = 0;j < surfacenumvertices;j++)
8477                                 {
8478                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8479                                         numvertices++;
8480                                 }
8481                         }
8482                 }
8483         }
8484
8485         // if vertices are deformed (sprite flares and things in maps, possibly
8486         // water waves, bulges and other deformations), modify the copied vertices
8487         // in place
8488         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8489         {
8490                 switch (deform->deform)
8491                 {
8492                 default:
8493                 case Q3DEFORM_PROJECTIONSHADOW:
8494                 case Q3DEFORM_TEXT0:
8495                 case Q3DEFORM_TEXT1:
8496                 case Q3DEFORM_TEXT2:
8497                 case Q3DEFORM_TEXT3:
8498                 case Q3DEFORM_TEXT4:
8499                 case Q3DEFORM_TEXT5:
8500                 case Q3DEFORM_TEXT6:
8501                 case Q3DEFORM_TEXT7:
8502                 case Q3DEFORM_NONE:
8503                         break;
8504                 case Q3DEFORM_AUTOSPRITE:
8505                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8506                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8507                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8508                         VectorNormalize(newforward);
8509                         VectorNormalize(newright);
8510                         VectorNormalize(newup);
8511 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8512 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8513 //                      rsurface.batchvertex3f_bufferoffset = 0;
8514 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8515 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8516 //                      rsurface.batchsvector3f_bufferoffset = 0;
8517 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8518 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8519 //                      rsurface.batchtvector3f_bufferoffset = 0;
8520 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8521 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8522 //                      rsurface.batchnormal3f_bufferoffset = 0;
8523                         // a single autosprite surface can contain multiple sprites...
8524                         for (j = 0;j < batchnumvertices - 3;j += 4)
8525                         {
8526                                 VectorClear(center);
8527                                 for (i = 0;i < 4;i++)
8528                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8529                                 VectorScale(center, 0.25f, center);
8530                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8531                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8532                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8533                                 for (i = 0;i < 4;i++)
8534                                 {
8535                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8536                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8537                                 }
8538                         }
8539                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8540                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8541                         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);
8542                         break;
8543                 case Q3DEFORM_AUTOSPRITE2:
8544                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8545                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8546                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8547                         VectorNormalize(newforward);
8548                         VectorNormalize(newright);
8549                         VectorNormalize(newup);
8550 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8551 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8552 //                      rsurface.batchvertex3f_bufferoffset = 0;
8553                         {
8554                                 const float *v1, *v2;
8555                                 vec3_t start, end;
8556                                 float f, l;
8557                                 struct
8558                                 {
8559                                         float length2;
8560                                         const float *v1;
8561                                         const float *v2;
8562                                 }
8563                                 shortest[2];
8564                                 memset(shortest, 0, sizeof(shortest));
8565                                 // a single autosprite surface can contain multiple sprites...
8566                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8567                                 {
8568                                         VectorClear(center);
8569                                         for (i = 0;i < 4;i++)
8570                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8571                                         VectorScale(center, 0.25f, center);
8572                                         // find the two shortest edges, then use them to define the
8573                                         // axis vectors for rotating around the central axis
8574                                         for (i = 0;i < 6;i++)
8575                                         {
8576                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8577                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8578                                                 l = VectorDistance2(v1, v2);
8579                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8580                                                 if (v1[2] != v2[2])
8581                                                         l += (1.0f / 1024.0f);
8582                                                 if (shortest[0].length2 > l || i == 0)
8583                                                 {
8584                                                         shortest[1] = shortest[0];
8585                                                         shortest[0].length2 = l;
8586                                                         shortest[0].v1 = v1;
8587                                                         shortest[0].v2 = v2;
8588                                                 }
8589                                                 else if (shortest[1].length2 > l || i == 1)
8590                                                 {
8591                                                         shortest[1].length2 = l;
8592                                                         shortest[1].v1 = v1;
8593                                                         shortest[1].v2 = v2;
8594                                                 }
8595                                         }
8596                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8597                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8598                                         // this calculates the right vector from the shortest edge
8599                                         // and the up vector from the edge midpoints
8600                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8601                                         VectorNormalize(right);
8602                                         VectorSubtract(end, start, up);
8603                                         VectorNormalize(up);
8604                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8605                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8606                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8607                                         VectorNegate(forward, forward);
8608                                         VectorReflect(forward, 0, up, forward);
8609                                         VectorNormalize(forward);
8610                                         CrossProduct(up, forward, newright);
8611                                         VectorNormalize(newright);
8612                                         // rotate the quad around the up axis vector, this is made
8613                                         // especially easy by the fact we know the quad is flat,
8614                                         // so we only have to subtract the center position and
8615                                         // measure distance along the right vector, and then
8616                                         // multiply that by the newright vector and add back the
8617                                         // center position
8618                                         // we also need to subtract the old position to undo the
8619                                         // displacement from the center, which we do with a
8620                                         // DotProduct, the subtraction/addition of center is also
8621                                         // optimized into DotProducts here
8622                                         l = DotProduct(right, center);
8623                                         for (i = 0;i < 4;i++)
8624                                         {
8625                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8626                                                 f = DotProduct(right, v1) - l;
8627                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8628                                         }
8629                                 }
8630                         }
8631                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8632                         {
8633 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8634 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8635 //                              rsurface.batchnormal3f_bufferoffset = 0;
8636                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8637                         }
8638                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8639                         {
8640 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8641 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8642 //                              rsurface.batchsvector3f_bufferoffset = 0;
8643 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8644 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8645 //                              rsurface.batchtvector3f_bufferoffset = 0;
8646                                 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);
8647                         }
8648                         break;
8649                 case Q3DEFORM_NORMAL:
8650                         // deform the normals to make reflections wavey
8651                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8652                         rsurface.batchnormal3f_vertexbuffer = NULL;
8653                         rsurface.batchnormal3f_bufferoffset = 0;
8654                         for (j = 0;j < batchnumvertices;j++)
8655                         {
8656                                 float vertex[3];
8657                                 float *normal = rsurface.batchnormal3f + 3*j;
8658                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8659                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8660                                 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]);
8661                                 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]);
8662                                 VectorNormalize(normal);
8663                         }
8664                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8665                         {
8666 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8667 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8668 //                              rsurface.batchsvector3f_bufferoffset = 0;
8669 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8670 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8671 //                              rsurface.batchtvector3f_bufferoffset = 0;
8672                                 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);
8673                         }
8674                         break;
8675                 case Q3DEFORM_WAVE:
8676                         // deform vertex array to make wavey water and flags and such
8677                         waveparms[0] = deform->waveparms[0];
8678                         waveparms[1] = deform->waveparms[1];
8679                         waveparms[2] = deform->waveparms[2];
8680                         waveparms[3] = deform->waveparms[3];
8681                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8682                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8683                         // this is how a divisor of vertex influence on deformation
8684                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8685                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8686 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8687 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8688 //                      rsurface.batchvertex3f_bufferoffset = 0;
8689 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8690 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8691 //                      rsurface.batchnormal3f_bufferoffset = 0;
8692                         for (j = 0;j < batchnumvertices;j++)
8693                         {
8694                                 // if the wavefunc depends on time, evaluate it per-vertex
8695                                 if (waveparms[3])
8696                                 {
8697                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8698                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8699                                 }
8700                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8701                         }
8702                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8703                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8704                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8705                         {
8706 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8707 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8708 //                              rsurface.batchsvector3f_bufferoffset = 0;
8709 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8710 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8711 //                              rsurface.batchtvector3f_bufferoffset = 0;
8712                                 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);
8713                         }
8714                         break;
8715                 case Q3DEFORM_BULGE:
8716                         // deform vertex array to make the surface have moving bulges
8717 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8718 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8719 //                      rsurface.batchvertex3f_bufferoffset = 0;
8720 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8721 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8722 //                      rsurface.batchnormal3f_bufferoffset = 0;
8723                         for (j = 0;j < batchnumvertices;j++)
8724                         {
8725                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8726                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8727                         }
8728                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8729                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8730                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8731                         {
8732 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8733 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8734 //                              rsurface.batchsvector3f_bufferoffset = 0;
8735 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8736 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8737 //                              rsurface.batchtvector3f_bufferoffset = 0;
8738                                 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);
8739                         }
8740                         break;
8741                 case Q3DEFORM_MOVE:
8742                         // deform vertex array
8743                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8744                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8745                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8746                         VectorScale(deform->parms, scale, waveparms);
8747 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8748 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8749 //                      rsurface.batchvertex3f_bufferoffset = 0;
8750                         for (j = 0;j < batchnumvertices;j++)
8751                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8752                         break;
8753                 }
8754         }
8755
8756         // generate texcoords based on the chosen texcoord source
8757         switch(rsurface.texture->tcgen.tcgen)
8758         {
8759         default:
8760         case Q3TCGEN_TEXTURE:
8761                 break;
8762         case Q3TCGEN_LIGHTMAP:
8763 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8764 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8765 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8766                 if (rsurface.batchtexcoordlightmap2f)
8767                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8768                 break;
8769         case Q3TCGEN_VECTOR:
8770 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8771 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8772 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8773                 for (j = 0;j < batchnumvertices;j++)
8774                 {
8775                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8776                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8777                 }
8778                 break;
8779         case Q3TCGEN_ENVIRONMENT:
8780                 // make environment reflections using a spheremap
8781                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8782                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8783                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8784                 for (j = 0;j < batchnumvertices;j++)
8785                 {
8786                         // identical to Q3A's method, but executed in worldspace so
8787                         // carried models can be shiny too
8788
8789                         float viewer[3], d, reflected[3], worldreflected[3];
8790
8791                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8792                         // VectorNormalize(viewer);
8793
8794                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8795
8796                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8797                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8798                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8799                         // note: this is proportinal to viewer, so we can normalize later
8800
8801                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8802                         VectorNormalize(worldreflected);
8803
8804                         // note: this sphere map only uses world x and z!
8805                         // so positive and negative y will LOOK THE SAME.
8806                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8807                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8808                 }
8809                 break;
8810         }
8811         // the only tcmod that needs software vertex processing is turbulent, so
8812         // check for it here and apply the changes if needed
8813         // and we only support that as the first one
8814         // (handling a mixture of turbulent and other tcmods would be problematic
8815         //  without punting it entirely to a software path)
8816         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8817         {
8818                 amplitude = rsurface.texture->tcmods[0].parms[1];
8819                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8820 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8821 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8822 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8823                 for (j = 0;j < batchnumvertices;j++)
8824                 {
8825                         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);
8826                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8827                 }
8828         }
8829
8830         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8831         {
8832                 // convert the modified arrays to vertex structs
8833 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8834 //              rsurface.batchvertexmeshbuffer = NULL;
8835                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8836                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8837                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8838                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8839                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8840                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8841                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8842                 {
8843                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8844                         {
8845                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8846                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8847                         }
8848                 }
8849                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8850                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8851                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8852                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8853                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8854                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8855                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8856                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8857                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8858         }
8859 }
8860
8861 void RSurf_DrawBatch(void)
8862 {
8863         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8864         // through the pipeline, killing it earlier in the pipeline would have
8865         // per-surface overhead rather than per-batch overhead, so it's best to
8866         // reject it here, before it hits glDraw.
8867         if (rsurface.batchnumtriangles == 0)
8868                 return;
8869 #if 0
8870         // batch debugging code
8871         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8872         {
8873                 int i;
8874                 int j;
8875                 int c;
8876                 const int *e;
8877                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8878                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8879                 {
8880                         c = e[i];
8881                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8882                         {
8883                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8884                                 {
8885                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8886                                                 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);
8887                                         break;
8888                                 }
8889                         }
8890                 }
8891         }
8892 #endif
8893         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);
8894 }
8895
8896 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8897 {
8898         // pick the closest matching water plane
8899         int planeindex, vertexindex, bestplaneindex = -1;
8900         float d, bestd;
8901         vec3_t vert;
8902         const float *v;
8903         r_waterstate_waterplane_t *p;
8904         qboolean prepared = false;
8905         bestd = 0;
8906         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8907         {
8908                 if(p->camera_entity != rsurface.texture->camera_entity)
8909                         continue;
8910                 d = 0;
8911                 if(!prepared)
8912                 {
8913                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8914                         prepared = true;
8915                         if(rsurface.batchnumvertices == 0)
8916                                 break;
8917                 }
8918                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8919                 {
8920                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8921                         d += fabs(PlaneDiff(vert, &p->plane));
8922                 }
8923                 if (bestd > d || bestplaneindex < 0)
8924                 {
8925                         bestd = d;
8926                         bestplaneindex = planeindex;
8927                 }
8928         }
8929         return bestplaneindex;
8930         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8931         // this situation though, as it might be better to render single larger
8932         // batches with useless stuff (backface culled for example) than to
8933         // render multiple smaller batches
8934 }
8935
8936 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8937 {
8938         int i;
8939         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8940         rsurface.passcolor4f_vertexbuffer = 0;
8941         rsurface.passcolor4f_bufferoffset = 0;
8942         for (i = 0;i < rsurface.batchnumvertices;i++)
8943                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8944 }
8945
8946 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8947 {
8948         int i;
8949         float f;
8950         const float *v;
8951         const float *c;
8952         float *c2;
8953         if (rsurface.passcolor4f)
8954         {
8955                 // generate color arrays
8956                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8957                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8958                 rsurface.passcolor4f_vertexbuffer = 0;
8959                 rsurface.passcolor4f_bufferoffset = 0;
8960                 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)
8961                 {
8962                         f = RSurf_FogVertex(v);
8963                         c2[0] = c[0] * f;
8964                         c2[1] = c[1] * f;
8965                         c2[2] = c[2] * f;
8966                         c2[3] = c[3];
8967                 }
8968         }
8969         else
8970         {
8971                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8972                 rsurface.passcolor4f_vertexbuffer = 0;
8973                 rsurface.passcolor4f_bufferoffset = 0;
8974                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8975                 {
8976                         f = RSurf_FogVertex(v);
8977                         c2[0] = f;
8978                         c2[1] = f;
8979                         c2[2] = f;
8980                         c2[3] = 1;
8981                 }
8982         }
8983 }
8984
8985 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8986 {
8987         int i;
8988         float f;
8989         const float *v;
8990         const float *c;
8991         float *c2;
8992         if (!rsurface.passcolor4f)
8993                 return;
8994         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8995         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8996         rsurface.passcolor4f_vertexbuffer = 0;
8997         rsurface.passcolor4f_bufferoffset = 0;
8998         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)
8999         {
9000                 f = RSurf_FogVertex(v);
9001                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9002                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9003                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9004                 c2[3] = c[3];
9005         }
9006 }
9007
9008 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9009 {
9010         int i;
9011         const float *c;
9012         float *c2;
9013         if (!rsurface.passcolor4f)
9014                 return;
9015         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9016         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9017         rsurface.passcolor4f_vertexbuffer = 0;
9018         rsurface.passcolor4f_bufferoffset = 0;
9019         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9020         {
9021                 c2[0] = c[0] * r;
9022                 c2[1] = c[1] * g;
9023                 c2[2] = c[2] * b;
9024                 c2[3] = c[3] * a;
9025         }
9026 }
9027
9028 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9029 {
9030         int i;
9031         const float *c;
9032         float *c2;
9033         if (!rsurface.passcolor4f)
9034                 return;
9035         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9036         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9037         rsurface.passcolor4f_vertexbuffer = 0;
9038         rsurface.passcolor4f_bufferoffset = 0;
9039         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9040         {
9041                 c2[0] = c[0] + r_refdef.scene.ambient;
9042                 c2[1] = c[1] + r_refdef.scene.ambient;
9043                 c2[2] = c[2] + r_refdef.scene.ambient;
9044                 c2[3] = c[3];
9045         }
9046 }
9047
9048 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9049 {
9050         // TODO: optimize
9051         rsurface.passcolor4f = NULL;
9052         rsurface.passcolor4f_vertexbuffer = 0;
9053         rsurface.passcolor4f_bufferoffset = 0;
9054         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9055         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9056         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9057         GL_Color(r, g, b, a);
9058         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9059         RSurf_DrawBatch();
9060 }
9061
9062 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9063 {
9064         // TODO: optimize applyfog && applycolor case
9065         // just apply fog if necessary, and tint the fog color array if necessary
9066         rsurface.passcolor4f = NULL;
9067         rsurface.passcolor4f_vertexbuffer = 0;
9068         rsurface.passcolor4f_bufferoffset = 0;
9069         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9070         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9071         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9072         GL_Color(r, g, b, a);
9073         RSurf_DrawBatch();
9074 }
9075
9076 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9077 {
9078         // TODO: optimize
9079         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9080         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9081         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9082         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9083         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9084         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9085         GL_Color(r, g, b, a);
9086         RSurf_DrawBatch();
9087 }
9088
9089 static void RSurf_DrawBatch_GL11_ClampColor(void)
9090 {
9091         int i;
9092         const float *c1;
9093         float *c2;
9094         if (!rsurface.passcolor4f)
9095                 return;
9096         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9097         {
9098                 c2[0] = bound(0.0f, c1[0], 1.0f);
9099                 c2[1] = bound(0.0f, c1[1], 1.0f);
9100                 c2[2] = bound(0.0f, c1[2], 1.0f);
9101                 c2[3] = bound(0.0f, c1[3], 1.0f);
9102         }
9103 }
9104
9105 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9106 {
9107         int i;
9108         float f;
9109         const float *v;
9110         const float *n;
9111         float *c;
9112         //vec3_t eyedir;
9113
9114         // fake shading
9115         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9116         rsurface.passcolor4f_vertexbuffer = 0;
9117         rsurface.passcolor4f_bufferoffset = 0;
9118         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)
9119         {
9120                 f = -DotProduct(r_refdef.view.forward, n);
9121                 f = max(0, f);
9122                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9123                 f *= r_refdef.lightmapintensity;
9124                 Vector4Set(c, f, f, f, 1);
9125         }
9126 }
9127
9128 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9129 {
9130         RSurf_DrawBatch_GL11_ApplyFakeLight();
9131         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9132         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9133         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9134         GL_Color(r, g, b, a);
9135         RSurf_DrawBatch();
9136 }
9137
9138 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9139 {
9140         int i;
9141         float f;
9142         float alpha;
9143         const float *v;
9144         const float *n;
9145         float *c;
9146         vec3_t ambientcolor;
9147         vec3_t diffusecolor;
9148         vec3_t lightdir;
9149         // TODO: optimize
9150         // model lighting
9151         VectorCopy(rsurface.modellight_lightdir, lightdir);
9152         f = 0.5f * r_refdef.lightmapintensity;
9153         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9154         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9155         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9156         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9157         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9158         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9159         alpha = *a;
9160         if (VectorLength2(diffusecolor) > 0)
9161         {
9162                 // q3-style directional shading
9163                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9164                 rsurface.passcolor4f_vertexbuffer = 0;
9165                 rsurface.passcolor4f_bufferoffset = 0;
9166                 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)
9167                 {
9168                         if ((f = DotProduct(n, lightdir)) > 0)
9169                                 VectorMA(ambientcolor, f, diffusecolor, c);
9170                         else
9171                                 VectorCopy(ambientcolor, c);
9172                         c[3] = alpha;
9173                 }
9174                 *r = 1;
9175                 *g = 1;
9176                 *b = 1;
9177                 *a = 1;
9178                 *applycolor = false;
9179         }
9180         else
9181         {
9182                 *r = ambientcolor[0];
9183                 *g = ambientcolor[1];
9184                 *b = ambientcolor[2];
9185                 rsurface.passcolor4f = NULL;
9186                 rsurface.passcolor4f_vertexbuffer = 0;
9187                 rsurface.passcolor4f_bufferoffset = 0;
9188         }
9189 }
9190
9191 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9192 {
9193         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9194         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9195         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9196         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9197         GL_Color(r, g, b, a);
9198         RSurf_DrawBatch();
9199 }
9200
9201 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9202 {
9203         int i;
9204         float f;
9205         const float *v;
9206         float *c;
9207         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9208         {
9209                 f = 1 - RSurf_FogVertex(v);
9210                 c[0] = r;
9211                 c[1] = g;
9212                 c[2] = b;
9213                 c[3] = f * a;
9214         }
9215 }
9216
9217 void RSurf_SetupDepthAndCulling(void)
9218 {
9219         // submodels are biased to avoid z-fighting with world surfaces that they
9220         // may be exactly overlapping (avoids z-fighting artifacts on certain
9221         // doors and things in Quake maps)
9222         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9223         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9224         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9225         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9226 }
9227
9228 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9229 {
9230         // transparent sky would be ridiculous
9231         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9232                 return;
9233         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9234         skyrenderlater = true;
9235         RSurf_SetupDepthAndCulling();
9236         GL_DepthMask(true);
9237         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9238         // skymasking on them, and Quake3 never did sky masking (unlike
9239         // software Quake and software Quake2), so disable the sky masking
9240         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9241         // and skymasking also looks very bad when noclipping outside the
9242         // level, so don't use it then either.
9243         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9244         {
9245                 R_Mesh_ResetTextureState();
9246                 if (skyrendermasked)
9247                 {
9248                         R_SetupShader_DepthOrShadow();
9249                         // depth-only (masking)
9250                         GL_ColorMask(0,0,0,0);
9251                         // just to make sure that braindead drivers don't draw
9252                         // anything despite that colormask...
9253                         GL_BlendFunc(GL_ZERO, GL_ONE);
9254                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9255                         if (rsurface.batchvertex3fbuffer)
9256                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9257                         else
9258                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9259                 }
9260                 else
9261                 {
9262                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9263                         // fog sky
9264                         GL_BlendFunc(GL_ONE, GL_ZERO);
9265                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9266                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9267                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9268                 }
9269                 RSurf_DrawBatch();
9270                 if (skyrendermasked)
9271                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9272         }
9273         R_Mesh_ResetTextureState();
9274         GL_Color(1, 1, 1, 1);
9275 }
9276
9277 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9278 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9279 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9280 {
9281         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9282                 return;
9283         if (prepass)
9284         {
9285                 // render screenspace normalmap to texture
9286                 GL_DepthMask(true);
9287                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9288                 RSurf_DrawBatch();
9289                 return;
9290         }
9291
9292         // bind lightmap texture
9293
9294         // water/refraction/reflection/camera surfaces have to be handled specially
9295         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9296         {
9297                 int start, end, startplaneindex;
9298                 for (start = 0;start < texturenumsurfaces;start = end)
9299                 {
9300                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9301                         if(startplaneindex < 0)
9302                         {
9303                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9304                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9305                                 end = start + 1;
9306                                 continue;
9307                         }
9308                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9309                                 ;
9310                         // now that we have a batch using the same planeindex, render it
9311                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9312                         {
9313                                 // render water or distortion background
9314                                 GL_DepthMask(true);
9315                                 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));
9316                                 RSurf_DrawBatch();
9317                                 // blend surface on top
9318                                 GL_DepthMask(false);
9319                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9320                                 RSurf_DrawBatch();
9321                         }
9322                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9323                         {
9324                                 // render surface with reflection texture as input
9325                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9326                                 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));
9327                                 RSurf_DrawBatch();
9328                         }
9329                 }
9330                 return;
9331         }
9332
9333         // render surface batch normally
9334         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9335         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9336         RSurf_DrawBatch();
9337 }
9338
9339 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9340 {
9341         // OpenGL 1.3 path - anything not completely ancient
9342         qboolean applycolor;
9343         qboolean applyfog;
9344         int layerindex;
9345         const texturelayer_t *layer;
9346         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);
9347         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9348
9349         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9350         {
9351                 vec4_t layercolor;
9352                 int layertexrgbscale;
9353                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9354                 {
9355                         if (layerindex == 0)
9356                                 GL_AlphaTest(true);
9357                         else
9358                         {
9359                                 GL_AlphaTest(false);
9360                                 GL_DepthFunc(GL_EQUAL);
9361                         }
9362                 }
9363                 GL_DepthMask(layer->depthmask && writedepth);
9364                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9365                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9366                 {
9367                         layertexrgbscale = 4;
9368                         VectorScale(layer->color, 0.25f, layercolor);
9369                 }
9370                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9371                 {
9372                         layertexrgbscale = 2;
9373                         VectorScale(layer->color, 0.5f, layercolor);
9374                 }
9375                 else
9376                 {
9377                         layertexrgbscale = 1;
9378                         VectorScale(layer->color, 1.0f, layercolor);
9379                 }
9380                 layercolor[3] = layer->color[3];
9381                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9382                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9383                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9384                 switch (layer->type)
9385                 {
9386                 case TEXTURELAYERTYPE_LITTEXTURE:
9387                         // single-pass lightmapped texture with 2x rgbscale
9388                         R_Mesh_TexBind(0, r_texture_white);
9389                         R_Mesh_TexMatrix(0, NULL);
9390                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9391                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9392                         R_Mesh_TexBind(1, layer->texture);
9393                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9394                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9395                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9396                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9397                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9398                         else if (FAKELIGHT_ENABLED)
9399                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9400                         else if (rsurface.uselightmaptexture)
9401                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9402                         else
9403                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9404                         break;
9405                 case TEXTURELAYERTYPE_TEXTURE:
9406                         // singletexture unlit texture with transparency support
9407                         R_Mesh_TexBind(0, layer->texture);
9408                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9409                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9410                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9411                         R_Mesh_TexBind(1, 0);
9412                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9413                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9414                         break;
9415                 case TEXTURELAYERTYPE_FOG:
9416                         // singletexture fogging
9417                         if (layer->texture)
9418                         {
9419                                 R_Mesh_TexBind(0, layer->texture);
9420                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9421                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9422                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9423                         }
9424                         else
9425                         {
9426                                 R_Mesh_TexBind(0, 0);
9427                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9428                         }
9429                         R_Mesh_TexBind(1, 0);
9430                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9431                         // generate a color array for the fog pass
9432                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9433                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9434                         RSurf_DrawBatch();
9435                         break;
9436                 default:
9437                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9438                 }
9439         }
9440         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9441         {
9442                 GL_DepthFunc(GL_LEQUAL);
9443                 GL_AlphaTest(false);
9444         }
9445 }
9446
9447 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9448 {
9449         // OpenGL 1.1 - crusty old voodoo path
9450         qboolean applyfog;
9451         int layerindex;
9452         const texturelayer_t *layer;
9453         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);
9454         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9455
9456         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9457         {
9458                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9459                 {
9460                         if (layerindex == 0)
9461                                 GL_AlphaTest(true);
9462                         else
9463                         {
9464                                 GL_AlphaTest(false);
9465                                 GL_DepthFunc(GL_EQUAL);
9466                         }
9467                 }
9468                 GL_DepthMask(layer->depthmask && writedepth);
9469                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9470                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9471                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9472                 switch (layer->type)
9473                 {
9474                 case TEXTURELAYERTYPE_LITTEXTURE:
9475                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9476                         {
9477                                 // two-pass lit texture with 2x rgbscale
9478                                 // first the lightmap pass
9479                                 R_Mesh_TexBind(0, r_texture_white);
9480                                 R_Mesh_TexMatrix(0, NULL);
9481                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9482                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9483                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9484                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9485                                 else if (FAKELIGHT_ENABLED)
9486                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9487                                 else if (rsurface.uselightmaptexture)
9488                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9489                                 else
9490                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9491                                 // then apply the texture to it
9492                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9493                                 R_Mesh_TexBind(0, layer->texture);
9494                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9495                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9496                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9497                                 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);
9498                         }
9499                         else
9500                         {
9501                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9502                                 R_Mesh_TexBind(0, layer->texture);
9503                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9504                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9505                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9506                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9507                                         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);
9508                                 else
9509                                         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);
9510                         }
9511                         break;
9512                 case TEXTURELAYERTYPE_TEXTURE:
9513                         // singletexture unlit texture with transparency support
9514                         R_Mesh_TexBind(0, layer->texture);
9515                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9516                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9517                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9518                         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);
9519                         break;
9520                 case TEXTURELAYERTYPE_FOG:
9521                         // singletexture fogging
9522                         if (layer->texture)
9523                         {
9524                                 R_Mesh_TexBind(0, layer->texture);
9525                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9526                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9527                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9528                         }
9529                         else
9530                         {
9531                                 R_Mesh_TexBind(0, 0);
9532                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9533                         }
9534                         // generate a color array for the fog pass
9535                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9536                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9537                         RSurf_DrawBatch();
9538                         break;
9539                 default:
9540                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9541                 }
9542         }
9543         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9544         {
9545                 GL_DepthFunc(GL_LEQUAL);
9546                 GL_AlphaTest(false);
9547         }
9548 }
9549
9550 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9551 {
9552         int vi;
9553         int j;
9554         r_vertexgeneric_t *batchvertex;
9555         float c[4];
9556
9557 //      R_Mesh_ResetTextureState();
9558         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9559
9560         if(rsurface.texture && rsurface.texture->currentskinframe)
9561         {
9562                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9563                 c[3] *= rsurface.texture->currentalpha;
9564         }
9565         else
9566         {
9567                 c[0] = 1;
9568                 c[1] = 0;
9569                 c[2] = 1;
9570                 c[3] = 1;
9571         }
9572
9573         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9574         {
9575                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9576                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9577                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9578         }
9579
9580         // brighten it up (as texture value 127 means "unlit")
9581         c[0] *= 2 * r_refdef.view.colorscale;
9582         c[1] *= 2 * r_refdef.view.colorscale;
9583         c[2] *= 2 * r_refdef.view.colorscale;
9584
9585         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9586                 c[3] *= r_wateralpha.value;
9587
9588         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9589         {
9590                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9591                 GL_DepthMask(false);
9592         }
9593         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9594         {
9595                 GL_BlendFunc(GL_ONE, GL_ONE);
9596                 GL_DepthMask(false);
9597         }
9598         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9599         {
9600                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9601                 GL_DepthMask(false);
9602         }
9603         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9604         {
9605                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9606                 GL_DepthMask(false);
9607         }
9608         else
9609         {
9610                 GL_BlendFunc(GL_ONE, GL_ZERO);
9611                 GL_DepthMask(writedepth);
9612         }
9613
9614         if (r_showsurfaces.integer == 3)
9615         {
9616                 rsurface.passcolor4f = NULL;
9617
9618                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9619                 {
9620                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9621
9622                         rsurface.passcolor4f = NULL;
9623                         rsurface.passcolor4f_vertexbuffer = 0;
9624                         rsurface.passcolor4f_bufferoffset = 0;
9625                 }
9626                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9627                 {
9628                         qboolean applycolor = true;
9629                         float one = 1.0;
9630
9631                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9632
9633                         r_refdef.lightmapintensity = 1;
9634                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9635                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9636                 }
9637                 else if (FAKELIGHT_ENABLED)
9638                 {
9639                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9640
9641                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9642                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9643                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9644                 }
9645                 else
9646                 {
9647                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9648
9649                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9650                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9651                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9652                 }
9653
9654                 if(!rsurface.passcolor4f)
9655                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9656
9657                 RSurf_DrawBatch_GL11_ApplyAmbient();
9658                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9659                 if(r_refdef.fogenabled)
9660                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9661                 RSurf_DrawBatch_GL11_ClampColor();
9662
9663                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9664                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9665                 RSurf_DrawBatch();
9666         }
9667         else if (!r_refdef.view.showdebug)
9668         {
9669                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9670                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9671                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9672                 {
9673                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9674                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9675                 }
9676                 R_Mesh_PrepareVertices_Generic_Unlock();
9677                 RSurf_DrawBatch();
9678         }
9679         else if (r_showsurfaces.integer == 4)
9680         {
9681                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9682                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9683                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9684                 {
9685                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9686                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9687                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9688                 }
9689                 R_Mesh_PrepareVertices_Generic_Unlock();
9690                 RSurf_DrawBatch();
9691         }
9692         else if (r_showsurfaces.integer == 2)
9693         {
9694                 const int *e;
9695                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9696                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9697                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9698                 {
9699                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9700                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9701                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9702                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9703                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9704                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9705                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9706                 }
9707                 R_Mesh_PrepareVertices_Generic_Unlock();
9708                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9709         }
9710         else
9711         {
9712                 int texturesurfaceindex;
9713                 int k;
9714                 const msurface_t *surface;
9715                 float surfacecolor4f[4];
9716                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9717                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9718                 vi = 0;
9719                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9720                 {
9721                         surface = texturesurfacelist[texturesurfaceindex];
9722                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9723                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9724                         for (j = 0;j < surface->num_vertices;j++)
9725                         {
9726                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9727                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9728                                 vi++;
9729                         }
9730                 }
9731                 R_Mesh_PrepareVertices_Generic_Unlock();
9732                 RSurf_DrawBatch();
9733         }
9734 }
9735
9736 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9737 {
9738         CHECKGLERROR
9739         RSurf_SetupDepthAndCulling();
9740         if (r_showsurfaces.integer)
9741         {
9742                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9743                 return;
9744         }
9745         switch (vid.renderpath)
9746         {
9747         case RENDERPATH_GL20:
9748         case RENDERPATH_D3D9:
9749         case RENDERPATH_D3D10:
9750         case RENDERPATH_D3D11:
9751         case RENDERPATH_SOFT:
9752         case RENDERPATH_GLES2:
9753                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9754                 break;
9755         case RENDERPATH_GL13:
9756                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9757                 break;
9758         case RENDERPATH_GL11:
9759                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9760                 break;
9761         }
9762         CHECKGLERROR
9763 }
9764
9765 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9766 {
9767         CHECKGLERROR
9768         RSurf_SetupDepthAndCulling();
9769         if (r_showsurfaces.integer)
9770         {
9771                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9772                 return;
9773         }
9774         switch (vid.renderpath)
9775         {
9776         case RENDERPATH_GL20:
9777         case RENDERPATH_D3D9:
9778         case RENDERPATH_D3D10:
9779         case RENDERPATH_D3D11:
9780         case RENDERPATH_SOFT:
9781         case RENDERPATH_GLES2:
9782                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9783                 break;
9784         case RENDERPATH_GL13:
9785                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9786                 break;
9787         case RENDERPATH_GL11:
9788                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9789                 break;
9790         }
9791         CHECKGLERROR
9792 }
9793
9794 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9795 {
9796         int i, j;
9797         int texturenumsurfaces, endsurface;
9798         texture_t *texture;
9799         const msurface_t *surface;
9800 #define MAXBATCH_TRANSPARENTSURFACES 256
9801         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9802
9803         // if the model is static it doesn't matter what value we give for
9804         // wantnormals and wanttangents, so this logic uses only rules applicable
9805         // to a model, knowing that they are meaningless otherwise
9806         if (ent == r_refdef.scene.worldentity)
9807                 RSurf_ActiveWorldEntity();
9808         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9809                 RSurf_ActiveModelEntity(ent, false, false, false);
9810         else
9811         {
9812                 switch (vid.renderpath)
9813                 {
9814                 case RENDERPATH_GL20:
9815                 case RENDERPATH_D3D9:
9816                 case RENDERPATH_D3D10:
9817                 case RENDERPATH_D3D11:
9818                 case RENDERPATH_SOFT:
9819                 case RENDERPATH_GLES2:
9820                         RSurf_ActiveModelEntity(ent, true, true, false);
9821                         break;
9822                 case RENDERPATH_GL13:
9823                 case RENDERPATH_GL11:
9824                         RSurf_ActiveModelEntity(ent, true, false, false);
9825                         break;
9826                 }
9827         }
9828
9829         if (r_transparentdepthmasking.integer)
9830         {
9831                 qboolean setup = false;
9832                 for (i = 0;i < numsurfaces;i = j)
9833                 {
9834                         j = i + 1;
9835                         surface = rsurface.modelsurfaces + surfacelist[i];
9836                         texture = surface->texture;
9837                         rsurface.texture = R_GetCurrentTexture(texture);
9838                         rsurface.lightmaptexture = NULL;
9839                         rsurface.deluxemaptexture = NULL;
9840                         rsurface.uselightmaptexture = false;
9841                         // scan ahead until we find a different texture
9842                         endsurface = min(i + 1024, numsurfaces);
9843                         texturenumsurfaces = 0;
9844                         texturesurfacelist[texturenumsurfaces++] = surface;
9845                         for (;j < endsurface;j++)
9846                         {
9847                                 surface = rsurface.modelsurfaces + surfacelist[j];
9848                                 if (texture != surface->texture)
9849                                         break;
9850                                 texturesurfacelist[texturenumsurfaces++] = surface;
9851                         }
9852                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9853                                 continue;
9854                         // render the range of surfaces as depth
9855                         if (!setup)
9856                         {
9857                                 setup = true;
9858                                 GL_ColorMask(0,0,0,0);
9859                                 GL_Color(1,1,1,1);
9860                                 GL_DepthTest(true);
9861                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9862                                 GL_DepthMask(true);
9863 //                              R_Mesh_ResetTextureState();
9864                                 R_SetupShader_DepthOrShadow();
9865                         }
9866                         RSurf_SetupDepthAndCulling();
9867                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9868                         if (rsurface.batchvertex3fbuffer)
9869                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9870                         else
9871                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9872                         RSurf_DrawBatch();
9873                 }
9874                 if (setup)
9875                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9876         }
9877
9878         for (i = 0;i < numsurfaces;i = j)
9879         {
9880                 j = i + 1;
9881                 surface = rsurface.modelsurfaces + surfacelist[i];
9882                 texture = surface->texture;
9883                 rsurface.texture = R_GetCurrentTexture(texture);
9884                 // scan ahead until we find a different texture
9885                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9886                 texturenumsurfaces = 0;
9887                 texturesurfacelist[texturenumsurfaces++] = surface;
9888                 if(FAKELIGHT_ENABLED)
9889                 {
9890                         rsurface.lightmaptexture = NULL;
9891                         rsurface.deluxemaptexture = NULL;
9892                         rsurface.uselightmaptexture = false;
9893                         for (;j < endsurface;j++)
9894                         {
9895                                 surface = rsurface.modelsurfaces + surfacelist[j];
9896                                 if (texture != surface->texture)
9897                                         break;
9898                                 texturesurfacelist[texturenumsurfaces++] = surface;
9899                         }
9900                 }
9901                 else
9902                 {
9903                         rsurface.lightmaptexture = surface->lightmaptexture;
9904                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9905                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9906                         for (;j < endsurface;j++)
9907                         {
9908                                 surface = rsurface.modelsurfaces + surfacelist[j];
9909                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9910                                         break;
9911                                 texturesurfacelist[texturenumsurfaces++] = surface;
9912                         }
9913                 }
9914                 // render the range of surfaces
9915                 if (ent == r_refdef.scene.worldentity)
9916                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9917                 else
9918                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9919         }
9920         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9921 }
9922
9923 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9924 {
9925         // transparent surfaces get pushed off into the transparent queue
9926         int surfacelistindex;
9927         const msurface_t *surface;
9928         vec3_t tempcenter, center;
9929         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9930         {
9931                 surface = texturesurfacelist[surfacelistindex];
9932                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9933                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9934                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9935                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9936                 if (queueentity->transparent_offset) // transparent offset
9937                 {
9938                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9939                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9940                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9941                 }
9942                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9943         }
9944 }
9945
9946 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9947 {
9948         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9949                 return;
9950         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9951                 return;
9952         RSurf_SetupDepthAndCulling();
9953         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9954         if (rsurface.batchvertex3fbuffer)
9955                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9956         else
9957                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9958         RSurf_DrawBatch();
9959 }
9960
9961 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9962 {
9963         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9964         CHECKGLERROR
9965         if (depthonly)
9966                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9967         else if (prepass)
9968         {
9969                 if (!rsurface.texture->currentnumlayers)
9970                         return;
9971                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9972                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9973                 else
9974                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9975         }
9976         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9977                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9978         else if (!rsurface.texture->currentnumlayers)
9979                 return;
9980         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9981         {
9982                 // in the deferred case, transparent surfaces were queued during prepass
9983                 if (!r_shadow_usingdeferredprepass)
9984                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9985         }
9986         else
9987         {
9988                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9989                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9990         }
9991         CHECKGLERROR
9992 }
9993
9994 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9995 {
9996         int i, j;
9997         texture_t *texture;
9998         R_FrameData_SetMark();
9999         // break the surface list down into batches by texture and use of lightmapping
10000         for (i = 0;i < numsurfaces;i = j)
10001         {
10002                 j = i + 1;
10003                 // texture is the base texture pointer, rsurface.texture is the
10004                 // current frame/skin the texture is directing us to use (for example
10005                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10006                 // use skin 1 instead)
10007                 texture = surfacelist[i]->texture;
10008                 rsurface.texture = R_GetCurrentTexture(texture);
10009                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10010                 {
10011                         // if this texture is not the kind we want, skip ahead to the next one
10012                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10013                                 ;
10014                         continue;
10015                 }
10016                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10017                 {
10018                         rsurface.lightmaptexture = NULL;
10019                         rsurface.deluxemaptexture = NULL;
10020                         rsurface.uselightmaptexture = false;
10021                         // simply scan ahead until we find a different texture or lightmap state
10022                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10023                                 ;
10024                 }
10025                 else
10026                 {
10027                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10028                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10029                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10030                         // simply scan ahead until we find a different texture or lightmap state
10031                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10032                                 ;
10033                 }
10034                 // render the range of surfaces
10035                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10036         }
10037         R_FrameData_ReturnToMark();
10038 }
10039
10040 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10041 {
10042         CHECKGLERROR
10043         if (depthonly)
10044                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10045         else if (prepass)
10046         {
10047                 if (!rsurface.texture->currentnumlayers)
10048                         return;
10049                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10050                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10051                 else
10052                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10053         }
10054         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10055                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10056         else if (!rsurface.texture->currentnumlayers)
10057                 return;
10058         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10059         {
10060                 // in the deferred case, transparent surfaces were queued during prepass
10061                 if (!r_shadow_usingdeferredprepass)
10062                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10063         }
10064         else
10065         {
10066                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10067                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10068         }
10069         CHECKGLERROR
10070 }
10071
10072 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10073 {
10074         int i, j;
10075         texture_t *texture;
10076         R_FrameData_SetMark();
10077         // break the surface list down into batches by texture and use of lightmapping
10078         for (i = 0;i < numsurfaces;i = j)
10079         {
10080                 j = i + 1;
10081                 // texture is the base texture pointer, rsurface.texture is the
10082                 // current frame/skin the texture is directing us to use (for example
10083                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10084                 // use skin 1 instead)
10085                 texture = surfacelist[i]->texture;
10086                 rsurface.texture = R_GetCurrentTexture(texture);
10087                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10088                 {
10089                         // if this texture is not the kind we want, skip ahead to the next one
10090                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10091                                 ;
10092                         continue;
10093                 }
10094                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10095                 {
10096                         rsurface.lightmaptexture = NULL;
10097                         rsurface.deluxemaptexture = NULL;
10098                         rsurface.uselightmaptexture = false;
10099                         // simply scan ahead until we find a different texture or lightmap state
10100                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10101                                 ;
10102                 }
10103                 else
10104                 {
10105                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10106                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10107                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10108                         // simply scan ahead until we find a different texture or lightmap state
10109                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10110                                 ;
10111                 }
10112                 // render the range of surfaces
10113                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10114         }
10115         R_FrameData_ReturnToMark();
10116 }
10117
10118 float locboxvertex3f[6*4*3] =
10119 {
10120         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10121         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10122         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10123         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10124         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10125         1,0,0, 0,0,0, 0,1,0, 1,1,0
10126 };
10127
10128 unsigned short locboxelements[6*2*3] =
10129 {
10130          0, 1, 2, 0, 2, 3,
10131          4, 5, 6, 4, 6, 7,
10132          8, 9,10, 8,10,11,
10133         12,13,14, 12,14,15,
10134         16,17,18, 16,18,19,
10135         20,21,22, 20,22,23
10136 };
10137
10138 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10139 {
10140         int i, j;
10141         cl_locnode_t *loc = (cl_locnode_t *)ent;
10142         vec3_t mins, size;
10143         float vertex3f[6*4*3];
10144         CHECKGLERROR
10145         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10146         GL_DepthMask(false);
10147         GL_DepthRange(0, 1);
10148         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10149         GL_DepthTest(true);
10150         GL_CullFace(GL_NONE);
10151         R_EntityMatrix(&identitymatrix);
10152
10153 //      R_Mesh_ResetTextureState();
10154
10155         i = surfacelist[0];
10156         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10157                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10158                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10159                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10160
10161         if (VectorCompare(loc->mins, loc->maxs))
10162         {
10163                 VectorSet(size, 2, 2, 2);
10164                 VectorMA(loc->mins, -0.5f, size, mins);
10165         }
10166         else
10167         {
10168                 VectorCopy(loc->mins, mins);
10169                 VectorSubtract(loc->maxs, loc->mins, size);
10170         }
10171
10172         for (i = 0;i < 6*4*3;)
10173                 for (j = 0;j < 3;j++, i++)
10174                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10175
10176         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10177         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10178         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10179 }
10180
10181 void R_DrawLocs(void)
10182 {
10183         int index;
10184         cl_locnode_t *loc, *nearestloc;
10185         vec3_t center;
10186         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10187         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10188         {
10189                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10190                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10191         }
10192 }
10193
10194 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10195 {
10196         if (decalsystem->decals)
10197                 Mem_Free(decalsystem->decals);
10198         memset(decalsystem, 0, sizeof(*decalsystem));
10199 }
10200
10201 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)
10202 {
10203         tridecal_t *decal;
10204         tridecal_t *decals;
10205         int i;
10206
10207         // expand or initialize the system
10208         if (decalsystem->maxdecals <= decalsystem->numdecals)
10209         {
10210                 decalsystem_t old = *decalsystem;
10211                 qboolean useshortelements;
10212                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10213                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10214                 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)));
10215                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10216                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10217                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10218                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10219                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10220                 if (decalsystem->numdecals)
10221                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10222                 if (old.decals)
10223                         Mem_Free(old.decals);
10224                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10225                         decalsystem->element3i[i] = i;
10226                 if (useshortelements)
10227                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10228                                 decalsystem->element3s[i] = i;
10229         }
10230
10231         // grab a decal and search for another free slot for the next one
10232         decals = decalsystem->decals;
10233         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10234         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10235                 ;
10236         decalsystem->freedecal = i;
10237         if (decalsystem->numdecals <= i)
10238                 decalsystem->numdecals = i + 1;
10239
10240         // initialize the decal
10241         decal->lived = 0;
10242         decal->triangleindex = triangleindex;
10243         decal->surfaceindex = surfaceindex;
10244         decal->decalsequence = decalsequence;
10245         decal->color4f[0][0] = c0[0];
10246         decal->color4f[0][1] = c0[1];
10247         decal->color4f[0][2] = c0[2];
10248         decal->color4f[0][3] = 1;
10249         decal->color4f[1][0] = c1[0];
10250         decal->color4f[1][1] = c1[1];
10251         decal->color4f[1][2] = c1[2];
10252         decal->color4f[1][3] = 1;
10253         decal->color4f[2][0] = c2[0];
10254         decal->color4f[2][1] = c2[1];
10255         decal->color4f[2][2] = c2[2];
10256         decal->color4f[2][3] = 1;
10257         decal->vertex3f[0][0] = v0[0];
10258         decal->vertex3f[0][1] = v0[1];
10259         decal->vertex3f[0][2] = v0[2];
10260         decal->vertex3f[1][0] = v1[0];
10261         decal->vertex3f[1][1] = v1[1];
10262         decal->vertex3f[1][2] = v1[2];
10263         decal->vertex3f[2][0] = v2[0];
10264         decal->vertex3f[2][1] = v2[1];
10265         decal->vertex3f[2][2] = v2[2];
10266         decal->texcoord2f[0][0] = t0[0];
10267         decal->texcoord2f[0][1] = t0[1];
10268         decal->texcoord2f[1][0] = t1[0];
10269         decal->texcoord2f[1][1] = t1[1];
10270         decal->texcoord2f[2][0] = t2[0];
10271         decal->texcoord2f[2][1] = t2[1];
10272 }
10273
10274 extern cvar_t cl_decals_bias;
10275 extern cvar_t cl_decals_models;
10276 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10277 // baseparms, parms, temps
10278 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)
10279 {
10280         int cornerindex;
10281         int index;
10282         float v[9][3];
10283         const float *vertex3f;
10284         const float *normal3f;
10285         int numpoints;
10286         float points[2][9][3];
10287         float temp[3];
10288         float tc[9][2];
10289         float f;
10290         float c[9][4];
10291         const int *e;
10292
10293         e = rsurface.modelelement3i + 3*triangleindex;
10294
10295         vertex3f = rsurface.modelvertex3f;
10296         normal3f = rsurface.modelnormal3f;
10297
10298         if (normal3f)
10299         {
10300                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10301                 {
10302                         index = 3*e[cornerindex];
10303                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10304                 }
10305         }
10306         else
10307         {
10308                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10309                 {
10310                         index = 3*e[cornerindex];
10311                         VectorCopy(vertex3f + index, v[cornerindex]);
10312                 }
10313         }
10314
10315         // cull backfaces
10316         //TriangleNormal(v[0], v[1], v[2], normal);
10317         //if (DotProduct(normal, localnormal) < 0.0f)
10318         //      continue;
10319         // clip by each of the box planes formed from the projection matrix
10320         // if anything survives, we emit the decal
10321         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]);
10322         if (numpoints < 3)
10323                 return;
10324         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]);
10325         if (numpoints < 3)
10326                 return;
10327         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]);
10328         if (numpoints < 3)
10329                 return;
10330         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]);
10331         if (numpoints < 3)
10332                 return;
10333         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]);
10334         if (numpoints < 3)
10335                 return;
10336         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]);
10337         if (numpoints < 3)
10338                 return;
10339         // some part of the triangle survived, so we have to accept it...
10340         if (dynamic)
10341         {
10342                 // dynamic always uses the original triangle
10343                 numpoints = 3;
10344                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10345                 {
10346                         index = 3*e[cornerindex];
10347                         VectorCopy(vertex3f + index, v[cornerindex]);
10348                 }
10349         }
10350         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10351         {
10352                 // convert vertex positions to texcoords
10353                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10354                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10355                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10356                 // calculate distance fade from the projection origin
10357                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10358                 f = bound(0.0f, f, 1.0f);
10359                 c[cornerindex][0] = r * f;
10360                 c[cornerindex][1] = g * f;
10361                 c[cornerindex][2] = b * f;
10362                 c[cornerindex][3] = 1.0f;
10363                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10364         }
10365         if (dynamic)
10366                 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);
10367         else
10368                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10369                         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);
10370 }
10371 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)
10372 {
10373         matrix4x4_t projection;
10374         decalsystem_t *decalsystem;
10375         qboolean dynamic;
10376         dp_model_t *model;
10377         const msurface_t *surface;
10378         const msurface_t *surfaces;
10379         const int *surfacelist;
10380         const texture_t *texture;
10381         int numtriangles;
10382         int numsurfacelist;
10383         int surfacelistindex;
10384         int surfaceindex;
10385         int triangleindex;
10386         float localorigin[3];
10387         float localnormal[3];
10388         float localmins[3];
10389         float localmaxs[3];
10390         float localsize;
10391         //float normal[3];
10392         float planes[6][4];
10393         float angles[3];
10394         bih_t *bih;
10395         int bih_triangles_count;
10396         int bih_triangles[256];
10397         int bih_surfaces[256];
10398
10399         decalsystem = &ent->decalsystem;
10400         model = ent->model;
10401         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10402         {
10403                 R_DecalSystem_Reset(&ent->decalsystem);
10404                 return;
10405         }
10406
10407         if (!model->brush.data_leafs && !cl_decals_models.integer)
10408         {
10409                 if (decalsystem->model)
10410                         R_DecalSystem_Reset(decalsystem);
10411                 return;
10412         }
10413
10414         if (decalsystem->model != model)
10415                 R_DecalSystem_Reset(decalsystem);
10416         decalsystem->model = model;
10417
10418         RSurf_ActiveModelEntity(ent, true, false, false);
10419
10420         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10421         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10422         VectorNormalize(localnormal);
10423         localsize = worldsize*rsurface.inversematrixscale;
10424         localmins[0] = localorigin[0] - localsize;
10425         localmins[1] = localorigin[1] - localsize;
10426         localmins[2] = localorigin[2] - localsize;
10427         localmaxs[0] = localorigin[0] + localsize;
10428         localmaxs[1] = localorigin[1] + localsize;
10429         localmaxs[2] = localorigin[2] + localsize;
10430
10431         //VectorCopy(localnormal, planes[4]);
10432         //VectorVectors(planes[4], planes[2], planes[0]);
10433         AnglesFromVectors(angles, localnormal, NULL, false);
10434         AngleVectors(angles, planes[0], planes[2], planes[4]);
10435         VectorNegate(planes[0], planes[1]);
10436         VectorNegate(planes[2], planes[3]);
10437         VectorNegate(planes[4], planes[5]);
10438         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10439         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10440         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10441         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10442         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10443         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10444
10445 #if 1
10446 // works
10447 {
10448         matrix4x4_t forwardprojection;
10449         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10450         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10451 }
10452 #else
10453 // broken
10454 {
10455         float projectionvector[4][3];
10456         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10457         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10458         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10459         projectionvector[0][0] = planes[0][0] * ilocalsize;
10460         projectionvector[0][1] = planes[1][0] * ilocalsize;
10461         projectionvector[0][2] = planes[2][0] * ilocalsize;
10462         projectionvector[1][0] = planes[0][1] * ilocalsize;
10463         projectionvector[1][1] = planes[1][1] * ilocalsize;
10464         projectionvector[1][2] = planes[2][1] * ilocalsize;
10465         projectionvector[2][0] = planes[0][2] * ilocalsize;
10466         projectionvector[2][1] = planes[1][2] * ilocalsize;
10467         projectionvector[2][2] = planes[2][2] * ilocalsize;
10468         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10469         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10470         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10471         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10472 }
10473 #endif
10474
10475         dynamic = model->surfmesh.isanimated;
10476         numsurfacelist = model->nummodelsurfaces;
10477         surfacelist = model->sortedmodelsurfaces;
10478         surfaces = model->data_surfaces;
10479
10480         bih = NULL;
10481         bih_triangles_count = -1;
10482         if(!dynamic)
10483         {
10484                 if(model->render_bih.numleafs)
10485                         bih = &model->render_bih;
10486                 else if(model->collision_bih.numleafs)
10487                         bih = &model->collision_bih;
10488         }
10489         if(bih)
10490                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10491         if(bih_triangles_count == 0)
10492                 return;
10493         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10494                 return;
10495         if(bih_triangles_count > 0)
10496         {
10497                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10498                 {
10499                         surfaceindex = bih_surfaces[triangleindex];
10500                         surface = surfaces + surfaceindex;
10501                         texture = surface->texture;
10502                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10503                                 continue;
10504                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10505                                 continue;
10506                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10507                 }
10508         }
10509         else
10510         {
10511                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10512                 {
10513                         surfaceindex = surfacelist[surfacelistindex];
10514                         surface = surfaces + surfaceindex;
10515                         // check cull box first because it rejects more than any other check
10516                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10517                                 continue;
10518                         // skip transparent surfaces
10519                         texture = surface->texture;
10520                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10521                                 continue;
10522                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10523                                 continue;
10524                         numtriangles = surface->num_triangles;
10525                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10526                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10527                 }
10528         }
10529 }
10530
10531 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10532 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)
10533 {
10534         int renderentityindex;
10535         float worldmins[3];
10536         float worldmaxs[3];
10537         entity_render_t *ent;
10538
10539         if (!cl_decals_newsystem.integer)
10540                 return;
10541
10542         worldmins[0] = worldorigin[0] - worldsize;
10543         worldmins[1] = worldorigin[1] - worldsize;
10544         worldmins[2] = worldorigin[2] - worldsize;
10545         worldmaxs[0] = worldorigin[0] + worldsize;
10546         worldmaxs[1] = worldorigin[1] + worldsize;
10547         worldmaxs[2] = worldorigin[2] + worldsize;
10548
10549         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10550
10551         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10552         {
10553                 ent = r_refdef.scene.entities[renderentityindex];
10554                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10555                         continue;
10556
10557                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10558         }
10559 }
10560
10561 typedef struct r_decalsystem_splatqueue_s
10562 {
10563         vec3_t worldorigin;
10564         vec3_t worldnormal;
10565         float color[4];
10566         float tcrange[4];
10567         float worldsize;
10568         int decalsequence;
10569 }
10570 r_decalsystem_splatqueue_t;
10571
10572 int r_decalsystem_numqueued = 0;
10573 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10574
10575 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)
10576 {
10577         r_decalsystem_splatqueue_t *queue;
10578
10579         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10580                 return;
10581
10582         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10583         VectorCopy(worldorigin, queue->worldorigin);
10584         VectorCopy(worldnormal, queue->worldnormal);
10585         Vector4Set(queue->color, r, g, b, a);
10586         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10587         queue->worldsize = worldsize;
10588         queue->decalsequence = cl.decalsequence++;
10589 }
10590
10591 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10592 {
10593         int i;
10594         r_decalsystem_splatqueue_t *queue;
10595
10596         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10597                 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);
10598         r_decalsystem_numqueued = 0;
10599 }
10600
10601 extern cvar_t cl_decals_max;
10602 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10603 {
10604         int i;
10605         decalsystem_t *decalsystem = &ent->decalsystem;
10606         int numdecals;
10607         int killsequence;
10608         tridecal_t *decal;
10609         float frametime;
10610         float lifetime;
10611
10612         if (!decalsystem->numdecals)
10613                 return;
10614
10615         if (r_showsurfaces.integer)
10616                 return;
10617
10618         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10619         {
10620                 R_DecalSystem_Reset(decalsystem);
10621                 return;
10622         }
10623
10624         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10625         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10626
10627         if (decalsystem->lastupdatetime)
10628                 frametime = (cl.time - decalsystem->lastupdatetime);
10629         else
10630                 frametime = 0;
10631         decalsystem->lastupdatetime = cl.time;
10632         decal = decalsystem->decals;
10633         numdecals = decalsystem->numdecals;
10634
10635         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10636         {
10637                 if (decal->color4f[0][3])
10638                 {
10639                         decal->lived += frametime;
10640                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10641                         {
10642                                 memset(decal, 0, sizeof(*decal));
10643                                 if (decalsystem->freedecal > i)
10644                                         decalsystem->freedecal = i;
10645                         }
10646                 }
10647         }
10648         decal = decalsystem->decals;
10649         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10650                 numdecals--;
10651
10652         // collapse the array by shuffling the tail decals into the gaps
10653         for (;;)
10654         {
10655                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10656                         decalsystem->freedecal++;
10657                 if (decalsystem->freedecal == numdecals)
10658                         break;
10659                 decal[decalsystem->freedecal] = decal[--numdecals];
10660         }
10661
10662         decalsystem->numdecals = numdecals;
10663
10664         if (numdecals <= 0)
10665         {
10666                 // if there are no decals left, reset decalsystem
10667                 R_DecalSystem_Reset(decalsystem);
10668         }
10669 }
10670
10671 extern skinframe_t *decalskinframe;
10672 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10673 {
10674         int i;
10675         decalsystem_t *decalsystem = &ent->decalsystem;
10676         int numdecals;
10677         tridecal_t *decal;
10678         float faderate;
10679         float alpha;
10680         float *v3f;
10681         float *c4f;
10682         float *t2f;
10683         const int *e;
10684         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10685         int numtris = 0;
10686
10687         numdecals = decalsystem->numdecals;
10688         if (!numdecals)
10689                 return;
10690
10691         if (r_showsurfaces.integer)
10692                 return;
10693
10694         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10695         {
10696                 R_DecalSystem_Reset(decalsystem);
10697                 return;
10698         }
10699
10700         // if the model is static it doesn't matter what value we give for
10701         // wantnormals and wanttangents, so this logic uses only rules applicable
10702         // to a model, knowing that they are meaningless otherwise
10703         if (ent == r_refdef.scene.worldentity)
10704                 RSurf_ActiveWorldEntity();
10705         else
10706                 RSurf_ActiveModelEntity(ent, false, false, false);
10707
10708         decalsystem->lastupdatetime = cl.time;
10709         decal = decalsystem->decals;
10710
10711         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10712
10713         // update vertex positions for animated models
10714         v3f = decalsystem->vertex3f;
10715         c4f = decalsystem->color4f;
10716         t2f = decalsystem->texcoord2f;
10717         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10718         {
10719                 if (!decal->color4f[0][3])
10720                         continue;
10721
10722                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10723                         continue;
10724
10725                 // update color values for fading decals
10726                 if (decal->lived >= cl_decals_time.value)
10727                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10728                 else
10729                         alpha = 1.0f;
10730
10731                 c4f[ 0] = decal->color4f[0][0] * alpha;
10732                 c4f[ 1] = decal->color4f[0][1] * alpha;
10733                 c4f[ 2] = decal->color4f[0][2] * alpha;
10734                 c4f[ 3] = 1;
10735                 c4f[ 4] = decal->color4f[1][0] * alpha;
10736                 c4f[ 5] = decal->color4f[1][1] * alpha;
10737                 c4f[ 6] = decal->color4f[1][2] * alpha;
10738                 c4f[ 7] = 1;
10739                 c4f[ 8] = decal->color4f[2][0] * alpha;
10740                 c4f[ 9] = decal->color4f[2][1] * alpha;
10741                 c4f[10] = decal->color4f[2][2] * alpha;
10742                 c4f[11] = 1;
10743
10744                 t2f[0] = decal->texcoord2f[0][0];
10745                 t2f[1] = decal->texcoord2f[0][1];
10746                 t2f[2] = decal->texcoord2f[1][0];
10747                 t2f[3] = decal->texcoord2f[1][1];
10748                 t2f[4] = decal->texcoord2f[2][0];
10749                 t2f[5] = decal->texcoord2f[2][1];
10750
10751                 // update vertex positions for animated models
10752                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10753                 {
10754                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10755                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10756                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10757                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10758                 }
10759                 else
10760                 {
10761                         VectorCopy(decal->vertex3f[0], v3f);
10762                         VectorCopy(decal->vertex3f[1], v3f + 3);
10763                         VectorCopy(decal->vertex3f[2], v3f + 6);
10764                 }
10765
10766                 if (r_refdef.fogenabled)
10767                 {
10768                         alpha = RSurf_FogVertex(v3f);
10769                         VectorScale(c4f, alpha, c4f);
10770                         alpha = RSurf_FogVertex(v3f + 3);
10771                         VectorScale(c4f + 4, alpha, c4f + 4);
10772                         alpha = RSurf_FogVertex(v3f + 6);
10773                         VectorScale(c4f + 8, alpha, c4f + 8);
10774                 }
10775
10776                 v3f += 9;
10777                 c4f += 12;
10778                 t2f += 6;
10779                 numtris++;
10780         }
10781
10782         if (numtris > 0)
10783         {
10784                 r_refdef.stats.drawndecals += numtris;
10785
10786                 // now render the decals all at once
10787                 // (this assumes they all use one particle font texture!)
10788                 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);
10789 //              R_Mesh_ResetTextureState();
10790                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10791                 GL_DepthMask(false);
10792                 GL_DepthRange(0, 1);
10793                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10794                 GL_DepthTest(true);
10795                 GL_CullFace(GL_NONE);
10796                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10797                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10798                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10799         }
10800 }
10801
10802 static void R_DrawModelDecals(void)
10803 {
10804         int i, numdecals;
10805
10806         // fade faster when there are too many decals
10807         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10808         for (i = 0;i < r_refdef.scene.numentities;i++)
10809                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10810
10811         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10812         for (i = 0;i < r_refdef.scene.numentities;i++)
10813                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10814                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10815
10816         R_DecalSystem_ApplySplatEntitiesQueue();
10817
10818         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10819         for (i = 0;i < r_refdef.scene.numentities;i++)
10820                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10821
10822         r_refdef.stats.totaldecals += numdecals;
10823
10824         if (r_showsurfaces.integer)
10825                 return;
10826
10827         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10828
10829         for (i = 0;i < r_refdef.scene.numentities;i++)
10830         {
10831                 if (!r_refdef.viewcache.entityvisible[i])
10832                         continue;
10833                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10834                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10835         }
10836 }
10837
10838 extern cvar_t mod_collision_bih;
10839 void R_DrawDebugModel(void)
10840 {
10841         entity_render_t *ent = rsurface.entity;
10842         int i, j, k, l, flagsmask;
10843         const msurface_t *surface;
10844         dp_model_t *model = ent->model;
10845         vec3_t v;
10846
10847         switch(vid.renderpath)
10848         {
10849         case RENDERPATH_GL11:
10850         case RENDERPATH_GL13:
10851         case RENDERPATH_GL20:
10852                 break;
10853         case RENDERPATH_D3D9:
10854                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10855                 return;
10856         case RENDERPATH_D3D10:
10857                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10858                 return;
10859         case RENDERPATH_D3D11:
10860                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10861                 return;
10862         case RENDERPATH_SOFT:
10863                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10864                 return;
10865         case RENDERPATH_GLES2:
10866                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10867                 return;
10868         }
10869
10870         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10871
10872 //      R_Mesh_ResetTextureState();
10873         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10874         GL_DepthRange(0, 1);
10875         GL_DepthTest(!r_showdisabledepthtest.integer);
10876         GL_DepthMask(false);
10877         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10878
10879         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10880         {
10881                 int triangleindex;
10882                 int bihleafindex;
10883                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10884                 const q3mbrush_t *brush;
10885                 const bih_t *bih = &model->collision_bih;
10886                 const bih_leaf_t *bihleaf;
10887                 float vertex3f[3][3];
10888                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10889                 cullbox = false;
10890                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10891                 {
10892                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10893                                 continue;
10894                         switch (bihleaf->type)
10895                         {
10896                         case BIH_BRUSH:
10897                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10898                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10899                                 {
10900                                         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);
10901                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10902                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10903                                 }
10904                                 break;
10905                         case BIH_COLLISIONTRIANGLE:
10906                                 triangleindex = bihleaf->itemindex;
10907                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10908                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10909                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10910                                 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);
10911                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10912                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10913                                 break;
10914                         case BIH_RENDERTRIANGLE:
10915                                 triangleindex = bihleaf->itemindex;
10916                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10917                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10918                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10919                                 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);
10920                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10921                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10922                                 break;
10923                         }
10924                 }
10925         }
10926
10927         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10928
10929         if (r_showtris.integer || (r_shownormals.value != 0))
10930         {
10931                 if (r_showdisabledepthtest.integer)
10932                 {
10933                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10934                         GL_DepthMask(false);
10935                 }
10936                 else
10937                 {
10938                         GL_BlendFunc(GL_ONE, GL_ZERO);
10939                         GL_DepthMask(true);
10940                 }
10941                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10942                 {
10943                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10944                                 continue;
10945                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10946                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10947                         {
10948                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10949                                 if (r_showtris.value > 0)
10950                                 {
10951                                         if (!rsurface.texture->currentlayers->depthmask)
10952                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10953                                         else if (ent == r_refdef.scene.worldentity)
10954                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10955                                         else
10956                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10957                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10958                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10959                                         RSurf_DrawBatch();
10960                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10961                                         CHECKGLERROR
10962                                 }
10963                                 if (r_shownormals.value < 0)
10964                                 {
10965                                         qglBegin(GL_LINES);
10966                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10967                                         {
10968                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10969                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10970                                                 qglVertex3f(v[0], v[1], v[2]);
10971                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10972                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10973                                                 qglVertex3f(v[0], v[1], v[2]);
10974                                         }
10975                                         qglEnd();
10976                                         CHECKGLERROR
10977                                 }
10978                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10979                                 {
10980                                         qglBegin(GL_LINES);
10981                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10982                                         {
10983                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10984                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10985                                                 qglVertex3f(v[0], v[1], v[2]);
10986                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10987                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10988                                                 qglVertex3f(v[0], v[1], v[2]);
10989                                         }
10990                                         qglEnd();
10991                                         CHECKGLERROR
10992                                         qglBegin(GL_LINES);
10993                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10994                                         {
10995                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10996                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10997                                                 qglVertex3f(v[0], v[1], v[2]);
10998                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10999                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11000                                                 qglVertex3f(v[0], v[1], v[2]);
11001                                         }
11002                                         qglEnd();
11003                                         CHECKGLERROR
11004                                         qglBegin(GL_LINES);
11005                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11006                                         {
11007                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11008                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11009                                                 qglVertex3f(v[0], v[1], v[2]);
11010                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11011                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11012                                                 qglVertex3f(v[0], v[1], v[2]);
11013                                         }
11014                                         qglEnd();
11015                                         CHECKGLERROR
11016                                 }
11017                         }
11018                 }
11019                 rsurface.texture = NULL;
11020         }
11021 }
11022
11023 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11024 int r_maxsurfacelist = 0;
11025 const msurface_t **r_surfacelist = NULL;
11026 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11027 {
11028         int i, j, endj, flagsmask;
11029         dp_model_t *model = r_refdef.scene.worldmodel;
11030         msurface_t *surfaces;
11031         unsigned char *update;
11032         int numsurfacelist = 0;
11033         if (model == NULL)
11034                 return;
11035
11036         if (r_maxsurfacelist < model->num_surfaces)
11037         {
11038                 r_maxsurfacelist = model->num_surfaces;
11039                 if (r_surfacelist)
11040                         Mem_Free((msurface_t**)r_surfacelist);
11041                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11042         }
11043
11044         RSurf_ActiveWorldEntity();
11045
11046         surfaces = model->data_surfaces;
11047         update = model->brushq1.lightmapupdateflags;
11048
11049         // update light styles on this submodel
11050         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11051         {
11052                 model_brush_lightstyleinfo_t *style;
11053                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11054                 {
11055                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11056                         {
11057                                 int *list = style->surfacelist;
11058                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11059                                 for (j = 0;j < style->numsurfaces;j++)
11060                                         update[list[j]] = true;
11061                         }
11062                 }
11063         }
11064
11065         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11066
11067         if (debug)
11068         {
11069                 R_DrawDebugModel();
11070                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11071                 return;
11072         }
11073
11074         rsurface.lightmaptexture = NULL;
11075         rsurface.deluxemaptexture = NULL;
11076         rsurface.uselightmaptexture = false;
11077         rsurface.texture = NULL;
11078         rsurface.rtlight = NULL;
11079         numsurfacelist = 0;
11080         // add visible surfaces to draw list
11081         for (i = 0;i < model->nummodelsurfaces;i++)
11082         {
11083                 j = model->sortedmodelsurfaces[i];
11084                 if (r_refdef.viewcache.world_surfacevisible[j])
11085                         r_surfacelist[numsurfacelist++] = surfaces + j;
11086         }
11087         // update lightmaps if needed
11088         if (model->brushq1.firstrender)
11089         {
11090                 model->brushq1.firstrender = false;
11091                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11092                         if (update[j])
11093                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11094         }
11095         else if (update)
11096         {
11097                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11098                         if (r_refdef.viewcache.world_surfacevisible[j])
11099                                 if (update[j])
11100                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11101         }
11102         // don't do anything if there were no surfaces
11103         if (!numsurfacelist)
11104         {
11105                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11106                 return;
11107         }
11108         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11109
11110         // add to stats if desired
11111         if (r_speeds.integer && !skysurfaces && !depthonly)
11112         {
11113                 r_refdef.stats.world_surfaces += numsurfacelist;
11114                 for (j = 0;j < numsurfacelist;j++)
11115                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11116         }
11117
11118         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11119 }
11120
11121 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11122 {
11123         int i, j, endj, flagsmask;
11124         dp_model_t *model = ent->model;
11125         msurface_t *surfaces;
11126         unsigned char *update;
11127         int numsurfacelist = 0;
11128         if (model == NULL)
11129                 return;
11130
11131         if (r_maxsurfacelist < model->num_surfaces)
11132         {
11133                 r_maxsurfacelist = model->num_surfaces;
11134                 if (r_surfacelist)
11135                         Mem_Free((msurface_t **)r_surfacelist);
11136                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11137         }
11138
11139         // if the model is static it doesn't matter what value we give for
11140         // wantnormals and wanttangents, so this logic uses only rules applicable
11141         // to a model, knowing that they are meaningless otherwise
11142         if (ent == r_refdef.scene.worldentity)
11143                 RSurf_ActiveWorldEntity();
11144         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11145                 RSurf_ActiveModelEntity(ent, false, false, false);
11146         else if (prepass)
11147                 RSurf_ActiveModelEntity(ent, true, true, true);
11148         else if (depthonly)
11149         {
11150                 switch (vid.renderpath)
11151                 {
11152                 case RENDERPATH_GL20:
11153                 case RENDERPATH_D3D9:
11154                 case RENDERPATH_D3D10:
11155                 case RENDERPATH_D3D11:
11156                 case RENDERPATH_SOFT:
11157                 case RENDERPATH_GLES2:
11158                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11159                         break;
11160                 case RENDERPATH_GL13:
11161                 case RENDERPATH_GL11:
11162                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11163                         break;
11164                 }
11165         }
11166         else
11167         {
11168                 switch (vid.renderpath)
11169                 {
11170                 case RENDERPATH_GL20:
11171                 case RENDERPATH_D3D9:
11172                 case RENDERPATH_D3D10:
11173                 case RENDERPATH_D3D11:
11174                 case RENDERPATH_SOFT:
11175                 case RENDERPATH_GLES2:
11176                         RSurf_ActiveModelEntity(ent, true, true, false);
11177                         break;
11178                 case RENDERPATH_GL13:
11179                 case RENDERPATH_GL11:
11180                         RSurf_ActiveModelEntity(ent, true, false, false);
11181                         break;
11182                 }
11183         }
11184
11185         surfaces = model->data_surfaces;
11186         update = model->brushq1.lightmapupdateflags;
11187
11188         // update light styles
11189         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11190         {
11191                 model_brush_lightstyleinfo_t *style;
11192                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11193                 {
11194                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11195                         {
11196                                 int *list = style->surfacelist;
11197                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11198                                 for (j = 0;j < style->numsurfaces;j++)
11199                                         update[list[j]] = true;
11200                         }
11201                 }
11202         }
11203
11204         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11205
11206         if (debug)
11207         {
11208                 R_DrawDebugModel();
11209                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11210                 return;
11211         }
11212
11213         rsurface.lightmaptexture = NULL;
11214         rsurface.deluxemaptexture = NULL;
11215         rsurface.uselightmaptexture = false;
11216         rsurface.texture = NULL;
11217         rsurface.rtlight = NULL;
11218         numsurfacelist = 0;
11219         // add visible surfaces to draw list
11220         for (i = 0;i < model->nummodelsurfaces;i++)
11221                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11222         // don't do anything if there were no surfaces
11223         if (!numsurfacelist)
11224         {
11225                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11226                 return;
11227         }
11228         // update lightmaps if needed
11229         if (update)
11230         {
11231                 int updated = 0;
11232                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11233                 {
11234                         if (update[j])
11235                         {
11236                                 updated++;
11237                                 R_BuildLightMap(ent, surfaces + j);
11238                         }
11239                 }
11240         }
11241         if (update)
11242                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11243                         if (update[j])
11244                                 R_BuildLightMap(ent, surfaces + j);
11245         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11246
11247         // add to stats if desired
11248         if (r_speeds.integer && !skysurfaces && !depthonly)
11249         {
11250                 r_refdef.stats.entities_surfaces += numsurfacelist;
11251                 for (j = 0;j < numsurfacelist;j++)
11252                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11253         }
11254
11255         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11256 }
11257
11258 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11259 {
11260         static texture_t texture;
11261         static msurface_t surface;
11262         const msurface_t *surfacelist = &surface;
11263
11264         // fake enough texture and surface state to render this geometry
11265
11266         texture.update_lastrenderframe = -1; // regenerate this texture
11267         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11268         texture.currentskinframe = skinframe;
11269         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11270         texture.offsetmapping = OFFSETMAPPING_OFF;
11271         texture.offsetscale = 1;
11272         texture.specularscalemod = 1;
11273         texture.specularpowermod = 1;
11274
11275         surface.texture = &texture;
11276         surface.num_triangles = numtriangles;
11277         surface.num_firsttriangle = firsttriangle;
11278         surface.num_vertices = numvertices;
11279         surface.num_firstvertex = firstvertex;
11280
11281         // now render it
11282         rsurface.texture = R_GetCurrentTexture(surface.texture);
11283         rsurface.lightmaptexture = NULL;
11284         rsurface.deluxemaptexture = NULL;
11285         rsurface.uselightmaptexture = false;
11286         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11287 }
11288
11289 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)
11290 {
11291         static msurface_t surface;
11292         const msurface_t *surfacelist = &surface;
11293
11294         // fake enough texture and surface state to render this geometry
11295         surface.texture = texture;
11296         surface.num_triangles = numtriangles;
11297         surface.num_firsttriangle = firsttriangle;
11298         surface.num_vertices = numvertices;
11299         surface.num_firstvertex = firstvertex;
11300
11301         // now render it
11302         rsurface.texture = R_GetCurrentTexture(surface.texture);
11303         rsurface.lightmaptexture = NULL;
11304         rsurface.deluxemaptexture = NULL;
11305         rsurface.uselightmaptexture = false;
11306         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11307 }