]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
added mod_collision_bih_childrengrouping cvar (default 16), this
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
121
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130
131 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
132 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
133
134 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
139
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143
144 cvar_t r_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)"};
145 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
146 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)"};
147 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
148 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)"};
149 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
150 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
151 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)"};
152 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)"};
153 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)"};
154 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)"};
155 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)"};
156 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)"};
157 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)"};
158 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)"};
159
160 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)"};
161 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
162 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"};
163 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
164 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
165 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
166
167 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
168 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
169 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
170 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
171
172 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
173 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
174 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
175 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
176 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
177 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
178 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
179
180 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
181 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
182 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
183 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)"};
184 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
185 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
186 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
187 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
188 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
189 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
190
191 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"};
192
193 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"};
194
195 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
196
197 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
198 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"};
199 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
200 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
201 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
202 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
203 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)"};
204 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
205 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
206
207 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
208 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"};
209
210 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."};
211
212 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)"};
213
214 extern cvar_t v_glslgamma;
215
216 extern qboolean v_flipped_state;
217
218 static struct r_bloomstate_s
219 {
220         qboolean enabled;
221         qboolean hdr;
222
223         int bloomwidth, bloomheight;
224
225         int screentexturewidth, screentextureheight;
226         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
227
228         int bloomtexturewidth, bloomtextureheight;
229         rtexture_t *texture_bloom;
230
231         // arrays for rendering the screen passes
232         float screentexcoord2f[8];
233         float bloomtexcoord2f[8];
234         float offsettexcoord2f[8];
235
236         r_viewport_t viewport;
237 }
238 r_bloomstate;
239
240 r_waterstate_t r_waterstate;
241
242 /// shadow volume bsp struct with automatically growing nodes buffer
243 svbsp_t r_svbsp;
244
245 rtexture_t *r_texture_blanknormalmap;
246 rtexture_t *r_texture_white;
247 rtexture_t *r_texture_grey128;
248 rtexture_t *r_texture_black;
249 rtexture_t *r_texture_notexture;
250 rtexture_t *r_texture_whitecube;
251 rtexture_t *r_texture_normalizationcube;
252 rtexture_t *r_texture_fogattenuation;
253 rtexture_t *r_texture_fogheighttexture;
254 rtexture_t *r_texture_gammaramps;
255 unsigned int r_texture_gammaramps_serial;
256 //rtexture_t *r_texture_fogintensity;
257 rtexture_t *r_texture_reflectcube;
258
259 // TODO: hash lookups?
260 typedef struct cubemapinfo_s
261 {
262         char basename[64];
263         rtexture_t *texture;
264 }
265 cubemapinfo_t;
266
267 int r_texture_numcubemaps;
268 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
269
270 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
271 unsigned int r_numqueries;
272 unsigned int r_maxqueries;
273
274 typedef struct r_qwskincache_s
275 {
276         char name[MAX_QPATH];
277         skinframe_t *skinframe;
278 }
279 r_qwskincache_t;
280
281 static r_qwskincache_t *r_qwskincache;
282 static int r_qwskincache_size;
283
284 /// vertex coordinates for a quad that covers the screen exactly
285 extern const float r_screenvertex3f[12];
286 extern const float r_d3dscreenvertex3f[12];
287 const float r_screenvertex3f[12] =
288 {
289         0, 0, 0,
290         1, 0, 0,
291         1, 1, 0,
292         0, 1, 0
293 };
294 const float r_d3dscreenvertex3f[12] =
295 {
296         0, 1, 0,
297         1, 1, 0,
298         1, 0, 0,
299         0, 0, 0
300 };
301
302 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
303 {
304         int i;
305         for (i = 0;i < verts;i++)
306         {
307                 out[0] = in[0] * r;
308                 out[1] = in[1] * g;
309                 out[2] = in[2] * b;
310                 out[3] = in[3];
311                 in += 4;
312                 out += 4;
313         }
314 }
315
316 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
317 {
318         int i;
319         for (i = 0;i < verts;i++)
320         {
321                 out[0] = r;
322                 out[1] = g;
323                 out[2] = b;
324                 out[3] = a;
325                 out += 4;
326         }
327 }
328
329 // FIXME: move this to client?
330 void FOG_clear(void)
331 {
332         if (gamemode == GAME_NEHAHRA)
333         {
334                 Cvar_Set("gl_fogenable", "0");
335                 Cvar_Set("gl_fogdensity", "0.2");
336                 Cvar_Set("gl_fogred", "0.3");
337                 Cvar_Set("gl_foggreen", "0.3");
338                 Cvar_Set("gl_fogblue", "0.3");
339         }
340         r_refdef.fog_density = 0;
341         r_refdef.fog_red = 0;
342         r_refdef.fog_green = 0;
343         r_refdef.fog_blue = 0;
344         r_refdef.fog_alpha = 1;
345         r_refdef.fog_start = 0;
346         r_refdef.fog_end = 16384;
347         r_refdef.fog_height = 1<<30;
348         r_refdef.fog_fadedepth = 128;
349         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
350 }
351
352 static void R_BuildBlankTextures(void)
353 {
354         unsigned char data[4];
355         data[2] = 128; // normal X
356         data[1] = 128; // normal Y
357         data[0] = 255; // normal Z
358         data[3] = 128; // height
359         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
360         data[0] = 255;
361         data[1] = 255;
362         data[2] = 255;
363         data[3] = 255;
364         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 128;
366         data[1] = 128;
367         data[2] = 128;
368         data[3] = 255;
369         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 0;
371         data[1] = 0;
372         data[2] = 0;
373         data[3] = 255;
374         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375 }
376
377 static void R_BuildNoTexture(void)
378 {
379         int x, y;
380         unsigned char pix[16][16][4];
381         // this makes a light grey/dark grey checkerboard texture
382         for (y = 0;y < 16;y++)
383         {
384                 for (x = 0;x < 16;x++)
385                 {
386                         if ((y < 8) ^ (x < 8))
387                         {
388                                 pix[y][x][0] = 128;
389                                 pix[y][x][1] = 128;
390                                 pix[y][x][2] = 128;
391                                 pix[y][x][3] = 255;
392                         }
393                         else
394                         {
395                                 pix[y][x][0] = 64;
396                                 pix[y][x][1] = 64;
397                                 pix[y][x][2] = 64;
398                                 pix[y][x][3] = 255;
399                         }
400                 }
401         }
402         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildWhiteCube(void)
406 {
407         unsigned char data[6*1*1*4];
408         memset(data, 255, sizeof(data));
409         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
410 }
411
412 static void R_BuildNormalizationCube(void)
413 {
414         int x, y, side;
415         vec3_t v;
416         vec_t s, t, intensity;
417 #define NORMSIZE 64
418         unsigned char *data;
419         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
420         for (side = 0;side < 6;side++)
421         {
422                 for (y = 0;y < NORMSIZE;y++)
423                 {
424                         for (x = 0;x < NORMSIZE;x++)
425                         {
426                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
427                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
428                                 switch(side)
429                                 {
430                                 default:
431                                 case 0:
432                                         v[0] = 1;
433                                         v[1] = -t;
434                                         v[2] = -s;
435                                         break;
436                                 case 1:
437                                         v[0] = -1;
438                                         v[1] = -t;
439                                         v[2] = s;
440                                         break;
441                                 case 2:
442                                         v[0] = s;
443                                         v[1] = 1;
444                                         v[2] = t;
445                                         break;
446                                 case 3:
447                                         v[0] = s;
448                                         v[1] = -1;
449                                         v[2] = -t;
450                                         break;
451                                 case 4:
452                                         v[0] = s;
453                                         v[1] = -t;
454                                         v[2] = 1;
455                                         break;
456                                 case 5:
457                                         v[0] = -s;
458                                         v[1] = -t;
459                                         v[2] = -1;
460                                         break;
461                                 }
462                                 intensity = 127.0f / sqrt(DotProduct(v, v));
463                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
464                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
465                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
466                                 data[((side*64+y)*64+x)*4+3] = 255;
467                         }
468                 }
469         }
470         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
471         Mem_Free(data);
472 }
473
474 static void R_BuildFogTexture(void)
475 {
476         int x, b;
477 #define FOGWIDTH 256
478         unsigned char data1[FOGWIDTH][4];
479         //unsigned char data2[FOGWIDTH][4];
480         double d, r, alpha;
481
482         r_refdef.fogmasktable_start = r_refdef.fog_start;
483         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
484         r_refdef.fogmasktable_range = r_refdef.fogrange;
485         r_refdef.fogmasktable_density = r_refdef.fog_density;
486
487         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
488         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
489         {
490                 d = (x * r - r_refdef.fogmasktable_start);
491                 if(developer_extra.integer)
492                         Con_DPrintf("%f ", d);
493                 d = max(0, d);
494                 if (r_fog_exp2.integer)
495                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
496                 else
497                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
498                 if(developer_extra.integer)
499                         Con_DPrintf(" : %f ", alpha);
500                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
501                 if(developer_extra.integer)
502                         Con_DPrintf(" = %f\n", alpha);
503                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
504         }
505
506         for (x = 0;x < FOGWIDTH;x++)
507         {
508                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
509                 data1[x][0] = b;
510                 data1[x][1] = b;
511                 data1[x][2] = b;
512                 data1[x][3] = 255;
513                 //data2[x][0] = 255 - b;
514                 //data2[x][1] = 255 - b;
515                 //data2[x][2] = 255 - b;
516                 //data2[x][3] = 255;
517         }
518         if (r_texture_fogattenuation)
519         {
520                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
521                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
522         }
523         else
524         {
525                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
526                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
527         }
528 }
529
530 static void R_BuildFogHeightTexture(void)
531 {
532         unsigned char *inpixels;
533         int size;
534         int x;
535         int y;
536         int j;
537         float c[4];
538         float f;
539         inpixels = NULL;
540         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
541         if (r_refdef.fogheighttexturename[0])
542                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
543         if (!inpixels)
544         {
545                 r_refdef.fog_height_tablesize = 0;
546                 if (r_texture_fogheighttexture)
547                         R_FreeTexture(r_texture_fogheighttexture);
548                 r_texture_fogheighttexture = NULL;
549                 if (r_refdef.fog_height_table2d)
550                         Mem_Free(r_refdef.fog_height_table2d);
551                 r_refdef.fog_height_table2d = NULL;
552                 if (r_refdef.fog_height_table1d)
553                         Mem_Free(r_refdef.fog_height_table1d);
554                 r_refdef.fog_height_table1d = NULL;
555                 return;
556         }
557         size = image_width;
558         r_refdef.fog_height_tablesize = size;
559         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
560         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
561         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
562         Mem_Free(inpixels);
563         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
564         // average fog color table accounting for every fog layer between a point
565         // and the camera.  (Note: attenuation is handled separately!)
566         for (y = 0;y < size;y++)
567         {
568                 for (x = 0;x < size;x++)
569                 {
570                         Vector4Clear(c);
571                         f = 0;
572                         if (x < y)
573                         {
574                                 for (j = x;j <= y;j++)
575                                 {
576                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
577                                         f++;
578                                 }
579                         }
580                         else
581                         {
582                                 for (j = x;j >= y;j--)
583                                 {
584                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
585                                         f++;
586                                 }
587                         }
588                         f = 1.0f / f;
589                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
590                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
591                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
592                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
593                 }
594         }
595         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
596 }
597
598 //=======================================================================================================================================================
599
600 static const char *builtinshaderstring =
601 #include "shader_glsl.h"
602 ;
603
604 const char *builtinhlslshaderstring =
605 #include "shader_hlsl.h"
606 ;
607
608 char *glslshaderstring = NULL;
609 char *hlslshaderstring = NULL;
610
611 //=======================================================================================================================================================
612
613 typedef struct shaderpermutationinfo_s
614 {
615         const char *pretext;
616         const char *name;
617 }
618 shaderpermutationinfo_t;
619
620 typedef struct shadermodeinfo_s
621 {
622         const char *vertexfilename;
623         const char *geometryfilename;
624         const char *fragmentfilename;
625         const char *pretext;
626         const char *name;
627 }
628 shadermodeinfo_t;
629
630 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
631 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
632 {
633         {"#define USEDIFFUSE\n", " diffuse"},
634         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
635         {"#define USEVIEWTINT\n", " viewtint"},
636         {"#define USECOLORMAPPING\n", " colormapping"},
637         {"#define USESATURATION\n", " saturation"},
638         {"#define USEFOGINSIDE\n", " foginside"},
639         {"#define USEFOGOUTSIDE\n", " fogoutside"},
640         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
641         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
642         {"#define USEGAMMARAMPS\n", " gammaramps"},
643         {"#define USECUBEFILTER\n", " cubefilter"},
644         {"#define USEGLOW\n", " glow"},
645         {"#define USEBLOOM\n", " bloom"},
646         {"#define USESPECULAR\n", " specular"},
647         {"#define USEPOSTPROCESSING\n", " postprocessing"},
648         {"#define USEREFLECTION\n", " reflection"},
649         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
650         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
651         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
652         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
653         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
654         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
655         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
656         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
657         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
658         {"#define USEALPHAKILL\n", " alphakill"},
659         {"#define USEREFLECTCUBE\n", " reflectcube"},
660         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
661         {"#define USEBOUNCEGRID\n", " bouncegrid"},
662         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
663 };
664
665 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
666 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
667 {
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
670         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
684 };
685
686 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
687 {
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 };
705
706 struct r_glsl_permutation_s;
707 typedef struct r_glsl_permutation_s
708 {
709         /// hash lookup data
710         struct r_glsl_permutation_s *hashnext;
711         unsigned int mode;
712         unsigned int permutation;
713
714         /// indicates if we have tried compiling this permutation already
715         qboolean compiled;
716         /// 0 if compilation failed
717         int program;
718         // texture units assigned to each detected uniform
719         int tex_Texture_First;
720         int tex_Texture_Second;
721         int tex_Texture_GammaRamps;
722         int tex_Texture_Normal;
723         int tex_Texture_Color;
724         int tex_Texture_Gloss;
725         int tex_Texture_Glow;
726         int tex_Texture_SecondaryNormal;
727         int tex_Texture_SecondaryColor;
728         int tex_Texture_SecondaryGloss;
729         int tex_Texture_SecondaryGlow;
730         int tex_Texture_Pants;
731         int tex_Texture_Shirt;
732         int tex_Texture_FogHeightTexture;
733         int tex_Texture_FogMask;
734         int tex_Texture_Lightmap;
735         int tex_Texture_Deluxemap;
736         int tex_Texture_Attenuation;
737         int tex_Texture_Cube;
738         int tex_Texture_Refraction;
739         int tex_Texture_Reflection;
740         int tex_Texture_ShadowMap2D;
741         int tex_Texture_CubeProjection;
742         int tex_Texture_ScreenDepth;
743         int tex_Texture_ScreenNormalMap;
744         int tex_Texture_ScreenDiffuse;
745         int tex_Texture_ScreenSpecular;
746         int tex_Texture_ReflectMask;
747         int tex_Texture_ReflectCube;
748         int tex_Texture_BounceGrid;
749         /// locations of detected uniforms in program object, or -1 if not found
750         int loc_Texture_First;
751         int loc_Texture_Second;
752         int loc_Texture_GammaRamps;
753         int loc_Texture_Normal;
754         int loc_Texture_Color;
755         int loc_Texture_Gloss;
756         int loc_Texture_Glow;
757         int loc_Texture_SecondaryNormal;
758         int loc_Texture_SecondaryColor;
759         int loc_Texture_SecondaryGloss;
760         int loc_Texture_SecondaryGlow;
761         int loc_Texture_Pants;
762         int loc_Texture_Shirt;
763         int loc_Texture_FogHeightTexture;
764         int loc_Texture_FogMask;
765         int loc_Texture_Lightmap;
766         int loc_Texture_Deluxemap;
767         int loc_Texture_Attenuation;
768         int loc_Texture_Cube;
769         int loc_Texture_Refraction;
770         int loc_Texture_Reflection;
771         int loc_Texture_ShadowMap2D;
772         int loc_Texture_CubeProjection;
773         int loc_Texture_ScreenDepth;
774         int loc_Texture_ScreenNormalMap;
775         int loc_Texture_ScreenDiffuse;
776         int loc_Texture_ScreenSpecular;
777         int loc_Texture_ReflectMask;
778         int loc_Texture_ReflectCube;
779         int loc_Texture_BounceGrid;
780         int loc_Alpha;
781         int loc_BloomBlur_Parameters;
782         int loc_ClientTime;
783         int loc_Color_Ambient;
784         int loc_Color_Diffuse;
785         int loc_Color_Specular;
786         int loc_Color_Glow;
787         int loc_Color_Pants;
788         int loc_Color_Shirt;
789         int loc_DeferredColor_Ambient;
790         int loc_DeferredColor_Diffuse;
791         int loc_DeferredColor_Specular;
792         int loc_DeferredMod_Diffuse;
793         int loc_DeferredMod_Specular;
794         int loc_DistortScaleRefractReflect;
795         int loc_EyePosition;
796         int loc_FogColor;
797         int loc_FogHeightFade;
798         int loc_FogPlane;
799         int loc_FogPlaneViewDist;
800         int loc_FogRangeRecip;
801         int loc_LightColor;
802         int loc_LightDir;
803         int loc_LightPosition;
804         int loc_OffsetMapping_ScaleSteps;
805         int loc_PixelSize;
806         int loc_ReflectColor;
807         int loc_ReflectFactor;
808         int loc_ReflectOffset;
809         int loc_RefractColor;
810         int loc_Saturation;
811         int loc_ScreenCenterRefractReflect;
812         int loc_ScreenScaleRefractReflect;
813         int loc_ScreenToDepth;
814         int loc_ShadowMap_Parameters;
815         int loc_ShadowMap_TextureScale;
816         int loc_SpecularPower;
817         int loc_UserVec1;
818         int loc_UserVec2;
819         int loc_UserVec3;
820         int loc_UserVec4;
821         int loc_ViewTintColor;
822         int loc_ViewToLight;
823         int loc_ModelToLight;
824         int loc_TexMatrix;
825         int loc_BackgroundTexMatrix;
826         int loc_ModelViewProjectionMatrix;
827         int loc_ModelViewMatrix;
828         int loc_PixelToScreenTexCoord;
829         int loc_ModelToReflectCube;
830         int loc_ShadowMapMatrix;
831         int loc_BloomColorSubtract;
832         int loc_NormalmapScrollBlend;
833         int loc_BounceGridMatrix;
834         int loc_BounceGridIntensity;
835 }
836 r_glsl_permutation_t;
837
838 #define SHADERPERMUTATION_HASHSIZE 256
839
840
841 // non-degradable "lightweight" shader parameters to keep the permutations simpler
842 // these can NOT degrade! only use for simple stuff
843 enum
844 {
845         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
846         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
847         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
851         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
852 };
853 #define SHADERSTATICPARMS_COUNT 7
854
855 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
856 static int shaderstaticparms_count = 0;
857
858 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
859 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
860 qboolean R_CompileShader_CheckStaticParms(void)
861 {
862         static int r_compileshader_staticparms_save[1];
863         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
864         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
865
866         // detect all
867         if (r_glsl_saturation_redcompensate.integer)
868                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
869         if (r_glsl_vertextextureblend_usebothalphas.integer)
870                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
871         if (r_shadow_glossexact.integer)
872                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
873         if (r_glsl_postprocess.integer)
874         {
875                 if (r_glsl_postprocess_uservec1_enable.integer)
876                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
877                 if (r_glsl_postprocess_uservec2_enable.integer)
878                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
879                 if (r_glsl_postprocess_uservec3_enable.integer)
880                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
881                 if (r_glsl_postprocess_uservec4_enable.integer)
882                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
883         }
884         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
885 }
886
887 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
888         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
889                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
890         else \
891                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
892 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
893 {
894         shaderstaticparms_count = 0;
895
896         // emit all
897         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
898         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
899         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
900         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
901         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
902         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
903         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
904 }
905
906 /// information about each possible shader permutation
907 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
908 /// currently selected permutation
909 r_glsl_permutation_t *r_glsl_permutation;
910 /// storage for permutations linked in the hash table
911 memexpandablearray_t r_glsl_permutationarray;
912
913 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
914 {
915         //unsigned int hashdepth = 0;
916         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
917         r_glsl_permutation_t *p;
918         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
919         {
920                 if (p->mode == mode && p->permutation == permutation)
921                 {
922                         //if (hashdepth > 10)
923                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
924                         return p;
925                 }
926                 //hashdepth++;
927         }
928         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
929         p->mode = mode;
930         p->permutation = permutation;
931         p->hashnext = r_glsl_permutationhash[mode][hashindex];
932         r_glsl_permutationhash[mode][hashindex] = p;
933         //if (hashdepth > 10)
934         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
935         return p;
936 }
937
938 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
939 {
940         char *shaderstring;
941         if (!filename || !filename[0])
942                 return NULL;
943         if (!strcmp(filename, "glsl/default.glsl"))
944         {
945                 if (!glslshaderstring)
946                 {
947                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
948                         if (glslshaderstring)
949                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
950                         else
951                                 glslshaderstring = (char *)builtinshaderstring;
952                 }
953                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
954                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
955                 return shaderstring;
956         }
957         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
958         if (shaderstring)
959         {
960                 if (printfromdisknotice)
961                         Con_DPrintf("from disk %s... ", filename);
962                 return shaderstring;
963         }
964         return shaderstring;
965 }
966
967 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
968 {
969         int i;
970         int sampler;
971         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
972         char *vertexstring, *geometrystring, *fragmentstring;
973         char permutationname[256];
974         int vertstrings_count = 0;
975         int geomstrings_count = 0;
976         int fragstrings_count = 0;
977         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
978         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
979         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
980
981         if (p->compiled)
982                 return;
983         p->compiled = true;
984         p->program = 0;
985
986         permutationname[0] = 0;
987         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
988         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
989         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
990
991         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
992
993         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
994         if(vid.support.gl20shaders130)
995         {
996                 vertstrings_list[vertstrings_count++] = "#version 130\n";
997                 geomstrings_list[geomstrings_count++] = "#version 130\n";
998                 fragstrings_list[fragstrings_count++] = "#version 130\n";
999                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1000                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1001                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1002         }
1003
1004         // the first pretext is which type of shader to compile as
1005         // (later these will all be bound together as a program object)
1006         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1007         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1008         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1009
1010         // the second pretext is the mode (for example a light source)
1011         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1012         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1013         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1014         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1015
1016         // now add all the permutation pretexts
1017         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1018         {
1019                 if (permutation & (1<<i))
1020                 {
1021                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1022                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1023                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1024                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1025                 }
1026                 else
1027                 {
1028                         // keep line numbers correct
1029                         vertstrings_list[vertstrings_count++] = "\n";
1030                         geomstrings_list[geomstrings_count++] = "\n";
1031                         fragstrings_list[fragstrings_count++] = "\n";
1032                 }
1033         }
1034
1035         // add static parms
1036         R_CompileShader_AddStaticParms(mode, permutation);
1037         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1038         vertstrings_count += shaderstaticparms_count;
1039         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1040         geomstrings_count += shaderstaticparms_count;
1041         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1042         fragstrings_count += shaderstaticparms_count;
1043
1044         // now append the shader text itself
1045         vertstrings_list[vertstrings_count++] = vertexstring;
1046         geomstrings_list[geomstrings_count++] = geometrystring;
1047         fragstrings_list[fragstrings_count++] = fragmentstring;
1048
1049         // if any sources were NULL, clear the respective list
1050         if (!vertexstring)
1051                 vertstrings_count = 0;
1052         if (!geometrystring)
1053                 geomstrings_count = 0;
1054         if (!fragmentstring)
1055                 fragstrings_count = 0;
1056
1057         // compile the shader program
1058         if (vertstrings_count + geomstrings_count + fragstrings_count)
1059                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1060         if (p->program)
1061         {
1062                 CHECKGLERROR
1063                 qglUseProgram(p->program);CHECKGLERROR
1064                 // look up all the uniform variable names we care about, so we don't
1065                 // have to look them up every time we set them
1066
1067                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1068                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1069                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1070                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1071                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1072                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1073                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1074                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1075                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1076                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1077                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1078                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1079                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1080                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1081                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1082                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1083                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1084                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1085                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1086                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1087                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1088                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1089                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1090                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1091                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1092                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1093                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1094                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1095                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1096                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1097                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1098                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1099                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1100                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1101                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1102                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1103                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1104                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1105                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1106                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1107                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1108                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1109                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1110                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1111                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1112                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1113                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1114                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1115                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1116                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1117                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1118                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1119                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1120                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1121                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1122                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1123                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1124                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1125                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1126                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1127                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1128                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1129                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1130                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1131                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1132                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1133                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1134                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1135                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1136                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1137                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1138                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1139                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1140                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1141                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1142                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1143                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1144                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1145                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1146                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1147                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1148                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1149                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1150                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1151                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1152                 // initialize the samplers to refer to the texture units we use
1153                 p->tex_Texture_First = -1;
1154                 p->tex_Texture_Second = -1;
1155                 p->tex_Texture_GammaRamps = -1;
1156                 p->tex_Texture_Normal = -1;
1157                 p->tex_Texture_Color = -1;
1158                 p->tex_Texture_Gloss = -1;
1159                 p->tex_Texture_Glow = -1;
1160                 p->tex_Texture_SecondaryNormal = -1;
1161                 p->tex_Texture_SecondaryColor = -1;
1162                 p->tex_Texture_SecondaryGloss = -1;
1163                 p->tex_Texture_SecondaryGlow = -1;
1164                 p->tex_Texture_Pants = -1;
1165                 p->tex_Texture_Shirt = -1;
1166                 p->tex_Texture_FogHeightTexture = -1;
1167                 p->tex_Texture_FogMask = -1;
1168                 p->tex_Texture_Lightmap = -1;
1169                 p->tex_Texture_Deluxemap = -1;
1170                 p->tex_Texture_Attenuation = -1;
1171                 p->tex_Texture_Cube = -1;
1172                 p->tex_Texture_Refraction = -1;
1173                 p->tex_Texture_Reflection = -1;
1174                 p->tex_Texture_ShadowMap2D = -1;
1175                 p->tex_Texture_CubeProjection = -1;
1176                 p->tex_Texture_ScreenDepth = -1;
1177                 p->tex_Texture_ScreenNormalMap = -1;
1178                 p->tex_Texture_ScreenDiffuse = -1;
1179                 p->tex_Texture_ScreenSpecular = -1;
1180                 p->tex_Texture_ReflectMask = -1;
1181                 p->tex_Texture_ReflectCube = -1;
1182                 p->tex_Texture_BounceGrid = -1;
1183                 sampler = 0;
1184                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1185                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1186                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1187                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1188                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1189                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1190                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1191                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1192                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1193                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1194                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1195                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1196                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1197                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1198                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1199                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1200                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1201                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1202                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1203                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1204                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1205                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1206                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1207                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1208                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1209                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1210                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1211                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1212                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1213                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1214                 CHECKGLERROR
1215                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1216         }
1217         else
1218                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1219
1220         // free the strings
1221         if (vertexstring)
1222                 Mem_Free(vertexstring);
1223         if (geometrystring)
1224                 Mem_Free(geometrystring);
1225         if (fragmentstring)
1226                 Mem_Free(fragmentstring);
1227 }
1228
1229 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1230 {
1231         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1232         if (r_glsl_permutation != perm)
1233         {
1234                 r_glsl_permutation = perm;
1235                 if (!r_glsl_permutation->program)
1236                 {
1237                         if (!r_glsl_permutation->compiled)
1238                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1239                         if (!r_glsl_permutation->program)
1240                         {
1241                                 // remove features until we find a valid permutation
1242                                 int i;
1243                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1244                                 {
1245                                         // reduce i more quickly whenever it would not remove any bits
1246                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1247                                         if (!(permutation & j))
1248                                                 continue;
1249                                         permutation -= j;
1250                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1251                                         if (!r_glsl_permutation->compiled)
1252                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1253                                         if (r_glsl_permutation->program)
1254                                                 break;
1255                                 }
1256                                 if (i >= SHADERPERMUTATION_COUNT)
1257                                 {
1258                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1259                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1260                                         qglUseProgram(0);CHECKGLERROR
1261                                         return; // no bit left to clear, entire mode is broken
1262                                 }
1263                         }
1264                 }
1265                 CHECKGLERROR
1266                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1267         }
1268         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1269         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1270         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1271 }
1272
1273 #ifdef SUPPORTD3D
1274
1275 #ifdef SUPPORTD3D
1276 #include <d3d9.h>
1277 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1278 extern D3DCAPS9 vid_d3d9caps;
1279 #endif
1280
1281 struct r_hlsl_permutation_s;
1282 typedef struct r_hlsl_permutation_s
1283 {
1284         /// hash lookup data
1285         struct r_hlsl_permutation_s *hashnext;
1286         unsigned int mode;
1287         unsigned int permutation;
1288
1289         /// indicates if we have tried compiling this permutation already
1290         qboolean compiled;
1291         /// NULL if compilation failed
1292         IDirect3DVertexShader9 *vertexshader;
1293         IDirect3DPixelShader9 *pixelshader;
1294 }
1295 r_hlsl_permutation_t;
1296
1297 typedef enum D3DVSREGISTER_e
1298 {
1299         D3DVSREGISTER_TexMatrix = 0, // float4x4
1300         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1301         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1302         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1303         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1304         D3DVSREGISTER_ModelToLight = 20, // float4x4
1305         D3DVSREGISTER_EyePosition = 24,
1306         D3DVSREGISTER_FogPlane = 25,
1307         D3DVSREGISTER_LightDir = 26,
1308         D3DVSREGISTER_LightPosition = 27,
1309 }
1310 D3DVSREGISTER_t;
1311
1312 typedef enum D3DPSREGISTER_e
1313 {
1314         D3DPSREGISTER_Alpha = 0,
1315         D3DPSREGISTER_BloomBlur_Parameters = 1,
1316         D3DPSREGISTER_ClientTime = 2,
1317         D3DPSREGISTER_Color_Ambient = 3,
1318         D3DPSREGISTER_Color_Diffuse = 4,
1319         D3DPSREGISTER_Color_Specular = 5,
1320         D3DPSREGISTER_Color_Glow = 6,
1321         D3DPSREGISTER_Color_Pants = 7,
1322         D3DPSREGISTER_Color_Shirt = 8,
1323         D3DPSREGISTER_DeferredColor_Ambient = 9,
1324         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1325         D3DPSREGISTER_DeferredColor_Specular = 11,
1326         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1327         D3DPSREGISTER_DeferredMod_Specular = 13,
1328         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1329         D3DPSREGISTER_EyePosition = 15, // unused
1330         D3DPSREGISTER_FogColor = 16,
1331         D3DPSREGISTER_FogHeightFade = 17,
1332         D3DPSREGISTER_FogPlane = 18,
1333         D3DPSREGISTER_FogPlaneViewDist = 19,
1334         D3DPSREGISTER_FogRangeRecip = 20,
1335         D3DPSREGISTER_LightColor = 21,
1336         D3DPSREGISTER_LightDir = 22, // unused
1337         D3DPSREGISTER_LightPosition = 23,
1338         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1339         D3DPSREGISTER_PixelSize = 25,
1340         D3DPSREGISTER_ReflectColor = 26,
1341         D3DPSREGISTER_ReflectFactor = 27,
1342         D3DPSREGISTER_ReflectOffset = 28,
1343         D3DPSREGISTER_RefractColor = 29,
1344         D3DPSREGISTER_Saturation = 30,
1345         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1346         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1347         D3DPSREGISTER_ScreenToDepth = 33,
1348         D3DPSREGISTER_ShadowMap_Parameters = 34,
1349         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1350         D3DPSREGISTER_SpecularPower = 36,
1351         D3DPSREGISTER_UserVec1 = 37,
1352         D3DPSREGISTER_UserVec2 = 38,
1353         D3DPSREGISTER_UserVec3 = 39,
1354         D3DPSREGISTER_UserVec4 = 40,
1355         D3DPSREGISTER_ViewTintColor = 41,
1356         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1357         D3DPSREGISTER_BloomColorSubtract = 43,
1358         D3DPSREGISTER_ViewToLight = 44, // float4x4
1359         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1360         D3DPSREGISTER_NormalmapScrollBlend = 52,
1361         // next at 53
1362 }
1363 D3DPSREGISTER_t;
1364
1365 /// information about each possible shader permutation
1366 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1367 /// currently selected permutation
1368 r_hlsl_permutation_t *r_hlsl_permutation;
1369 /// storage for permutations linked in the hash table
1370 memexpandablearray_t r_hlsl_permutationarray;
1371
1372 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1373 {
1374         //unsigned int hashdepth = 0;
1375         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1376         r_hlsl_permutation_t *p;
1377         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1378         {
1379                 if (p->mode == mode && p->permutation == permutation)
1380                 {
1381                         //if (hashdepth > 10)
1382                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1383                         return p;
1384                 }
1385                 //hashdepth++;
1386         }
1387         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1388         p->mode = mode;
1389         p->permutation = permutation;
1390         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1391         r_hlsl_permutationhash[mode][hashindex] = p;
1392         //if (hashdepth > 10)
1393         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1394         return p;
1395 }
1396
1397 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1398 {
1399         char *shaderstring;
1400         if (!filename || !filename[0])
1401                 return NULL;
1402         if (!strcmp(filename, "hlsl/default.hlsl"))
1403         {
1404                 if (!hlslshaderstring)
1405                 {
1406                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1407                         if (hlslshaderstring)
1408                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1409                         else
1410                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1411                 }
1412                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1413                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1414                 return shaderstring;
1415         }
1416         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1417         if (shaderstring)
1418         {
1419                 if (printfromdisknotice)
1420                         Con_DPrintf("from disk %s... ", filename);
1421                 return shaderstring;
1422         }
1423         return shaderstring;
1424 }
1425
1426 #include <d3dx9.h>
1427 //#include <d3dx9shader.h>
1428 //#include <d3dx9mesh.h>
1429
1430 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1431 {
1432         DWORD *vsbin = NULL;
1433         DWORD *psbin = NULL;
1434         fs_offset_t vsbinsize;
1435         fs_offset_t psbinsize;
1436 //      IDirect3DVertexShader9 *vs = NULL;
1437 //      IDirect3DPixelShader9 *ps = NULL;
1438         ID3DXBuffer *vslog = NULL;
1439         ID3DXBuffer *vsbuffer = NULL;
1440         ID3DXConstantTable *vsconstanttable = NULL;
1441         ID3DXBuffer *pslog = NULL;
1442         ID3DXBuffer *psbuffer = NULL;
1443         ID3DXConstantTable *psconstanttable = NULL;
1444         int vsresult = 0;
1445         int psresult = 0;
1446         char temp[MAX_INPUTLINE];
1447         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1448         qboolean debugshader = gl_paranoid.integer != 0;
1449         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1450         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1451         if (!debugshader)
1452         {
1453                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1454                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1455         }
1456         if ((!vsbin && vertstring) || (!psbin && fragstring))
1457         {
1458                 const char* dllnames_d3dx9 [] =
1459                 {
1460                         "d3dx9_43.dll",
1461                         "d3dx9_42.dll",
1462                         "d3dx9_41.dll",
1463                         "d3dx9_40.dll",
1464                         "d3dx9_39.dll",
1465                         "d3dx9_38.dll",
1466                         "d3dx9_37.dll",
1467                         "d3dx9_36.dll",
1468                         "d3dx9_35.dll",
1469                         "d3dx9_34.dll",
1470                         "d3dx9_33.dll",
1471                         "d3dx9_32.dll",
1472                         "d3dx9_31.dll",
1473                         "d3dx9_30.dll",
1474                         "d3dx9_29.dll",
1475                         "d3dx9_28.dll",
1476                         "d3dx9_27.dll",
1477                         "d3dx9_26.dll",
1478                         "d3dx9_25.dll",
1479                         "d3dx9_24.dll",
1480                         NULL
1481                 };
1482                 dllhandle_t d3dx9_dll = NULL;
1483                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1484                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1485                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1486                 dllfunction_t d3dx9_dllfuncs[] =
1487                 {
1488                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1489                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1490                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1491                         {NULL, NULL}
1492                 };
1493                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1494                 {
1495                         DWORD shaderflags = 0;
1496                         if (debugshader)
1497                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1498                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1499                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1500                         if (vertstring && vertstring[0])
1501                         {
1502                                 if (debugshader)
1503                                 {
1504 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1505 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1506                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1507                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1508                                 }
1509                                 else
1510                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1511                                 if (vsbuffer)
1512                                 {
1513                                         vsbinsize = vsbuffer->GetBufferSize();
1514                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1515                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1516                                         vsbuffer->Release();
1517                                 }
1518                                 if (vslog)
1519                                 {
1520                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1521                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1522                                         vslog->Release();
1523                                 }
1524                         }
1525                         if (fragstring && fragstring[0])
1526                         {
1527                                 if (debugshader)
1528                                 {
1529 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1530 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1531                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1532                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1533                                 }
1534                                 else
1535                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1536                                 if (psbuffer)
1537                                 {
1538                                         psbinsize = psbuffer->GetBufferSize();
1539                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1540                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1541                                         psbuffer->Release();
1542                                 }
1543                                 if (pslog)
1544                                 {
1545                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1546                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1547                                         pslog->Release();
1548                                 }
1549                         }
1550                         Sys_UnloadLibrary(&d3dx9_dll);
1551                 }
1552                 else
1553                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1554         }
1555         if (vsbin && psbin)
1556         {
1557                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1558                 if (FAILED(vsresult))
1559                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1560                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1561                 if (FAILED(psresult))
1562                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1563         }
1564         // free the shader data
1565         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1566         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1567 }
1568
1569 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1570 {
1571         int i;
1572         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1573         int vertstring_length = 0;
1574         int geomstring_length = 0;
1575         int fragstring_length = 0;
1576         char *t;
1577         char *vertexstring, *geometrystring, *fragmentstring;
1578         char *vertstring, *geomstring, *fragstring;
1579         char permutationname[256];
1580         char cachename[256];
1581         int vertstrings_count = 0;
1582         int geomstrings_count = 0;
1583         int fragstrings_count = 0;
1584         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1585         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1586         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1587
1588         if (p->compiled)
1589                 return;
1590         p->compiled = true;
1591         p->vertexshader = NULL;
1592         p->pixelshader = NULL;
1593
1594         permutationname[0] = 0;
1595         cachename[0] = 0;
1596         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1597         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1598         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1599
1600         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1601         strlcat(cachename, "hlsl/", sizeof(cachename));
1602
1603         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1604         vertstrings_count = 0;
1605         geomstrings_count = 0;
1606         fragstrings_count = 0;
1607         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1608         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1609         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1610
1611         // the first pretext is which type of shader to compile as
1612         // (later these will all be bound together as a program object)
1613         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1614         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1615         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1616
1617         // the second pretext is the mode (for example a light source)
1618         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1619         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1620         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1621         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1622         strlcat(cachename, modeinfo->name, sizeof(cachename));
1623
1624         // now add all the permutation pretexts
1625         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1626         {
1627                 if (permutation & (1<<i))
1628                 {
1629                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1630                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1631                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1632                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1633                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1634                 }
1635                 else
1636                 {
1637                         // keep line numbers correct
1638                         vertstrings_list[vertstrings_count++] = "\n";
1639                         geomstrings_list[geomstrings_count++] = "\n";
1640                         fragstrings_list[fragstrings_count++] = "\n";
1641                 }
1642         }
1643
1644         // add static parms
1645         R_CompileShader_AddStaticParms(mode, permutation);
1646         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1647         vertstrings_count += shaderstaticparms_count;
1648         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1649         geomstrings_count += shaderstaticparms_count;
1650         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1651         fragstrings_count += shaderstaticparms_count;
1652
1653         // replace spaces in the cachename with _ characters
1654         for (i = 0;cachename[i];i++)
1655                 if (cachename[i] == ' ')
1656                         cachename[i] = '_';
1657
1658         // now append the shader text itself
1659         vertstrings_list[vertstrings_count++] = vertexstring;
1660         geomstrings_list[geomstrings_count++] = geometrystring;
1661         fragstrings_list[fragstrings_count++] = fragmentstring;
1662
1663         // if any sources were NULL, clear the respective list
1664         if (!vertexstring)
1665                 vertstrings_count = 0;
1666         if (!geometrystring)
1667                 geomstrings_count = 0;
1668         if (!fragmentstring)
1669                 fragstrings_count = 0;
1670
1671         vertstring_length = 0;
1672         for (i = 0;i < vertstrings_count;i++)
1673                 vertstring_length += strlen(vertstrings_list[i]);
1674         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1675         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1676                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1677
1678         geomstring_length = 0;
1679         for (i = 0;i < geomstrings_count;i++)
1680                 geomstring_length += strlen(geomstrings_list[i]);
1681         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1682         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1683                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1684
1685         fragstring_length = 0;
1686         for (i = 0;i < fragstrings_count;i++)
1687                 fragstring_length += strlen(fragstrings_list[i]);
1688         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1689         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1690                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1691
1692         // try to load the cached shader, or generate one
1693         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1694
1695         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1696                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1697         else
1698                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1699
1700         // free the strings
1701         if (vertstring)
1702                 Mem_Free(vertstring);
1703         if (geomstring)
1704                 Mem_Free(geomstring);
1705         if (fragstring)
1706                 Mem_Free(fragstring);
1707         if (vertexstring)
1708                 Mem_Free(vertexstring);
1709         if (geometrystring)
1710                 Mem_Free(geometrystring);
1711         if (fragmentstring)
1712                 Mem_Free(fragmentstring);
1713 }
1714
1715 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1716 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1717 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);}
1718 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);}
1719 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);}
1720 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);}
1721
1722 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1723 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1724 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);}
1725 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);}
1726 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);}
1727 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);}
1728
1729 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1730 {
1731         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1732         if (r_hlsl_permutation != perm)
1733         {
1734                 r_hlsl_permutation = perm;
1735                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1736                 {
1737                         if (!r_hlsl_permutation->compiled)
1738                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1739                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1740                         {
1741                                 // remove features until we find a valid permutation
1742                                 int i;
1743                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1744                                 {
1745                                         // reduce i more quickly whenever it would not remove any bits
1746                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1747                                         if (!(permutation & j))
1748                                                 continue;
1749                                         permutation -= j;
1750                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1751                                         if (!r_hlsl_permutation->compiled)
1752                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1753                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1754                                                 break;
1755                                 }
1756                                 if (i >= SHADERPERMUTATION_COUNT)
1757                                 {
1758                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1759                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1760                                         return; // no bit left to clear, entire mode is broken
1761                                 }
1762                         }
1763                 }
1764                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1765                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1766         }
1767         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1768         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1769         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1770 }
1771 #endif
1772
1773 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1774 {
1775         DPSOFTRAST_SetShader(mode, permutation);
1776         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1777         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1778         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1779 }
1780
1781 void R_GLSL_Restart_f(void)
1782 {
1783         unsigned int i, limit;
1784         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1785                 Mem_Free(glslshaderstring);
1786         glslshaderstring = NULL;
1787         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1788                 Mem_Free(hlslshaderstring);
1789         hlslshaderstring = NULL;
1790         switch(vid.renderpath)
1791         {
1792         case RENDERPATH_D3D9:
1793 #ifdef SUPPORTD3D
1794                 {
1795                         r_hlsl_permutation_t *p;
1796                         r_hlsl_permutation = NULL;
1797                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1798                         for (i = 0;i < limit;i++)
1799                         {
1800                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1801                                 {
1802                                         if (p->vertexshader)
1803                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1804                                         if (p->pixelshader)
1805                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1806                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1807                                 }
1808                         }
1809                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1810                 }
1811 #endif
1812                 break;
1813         case RENDERPATH_D3D10:
1814                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1815                 break;
1816         case RENDERPATH_D3D11:
1817                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1818                 break;
1819         case RENDERPATH_GL20:
1820         case RENDERPATH_GLES2:
1821                 {
1822                         r_glsl_permutation_t *p;
1823                         r_glsl_permutation = NULL;
1824                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1825                         for (i = 0;i < limit;i++)
1826                         {
1827                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1828                                 {
1829                                         GL_Backend_FreeProgram(p->program);
1830                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1831                                 }
1832                         }
1833                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1834                 }
1835                 break;
1836         case RENDERPATH_GL13:
1837         case RENDERPATH_GL11:
1838                 break;
1839         case RENDERPATH_SOFT:
1840                 break;
1841         }
1842 }
1843
1844 void R_GLSL_DumpShader_f(void)
1845 {
1846         int i;
1847         qfile_t *file;
1848
1849         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1850         if (file)
1851         {
1852                 FS_Print(file, "/* The engine may define the following macros:\n");
1853                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1854                 for (i = 0;i < SHADERMODE_COUNT;i++)
1855                         FS_Print(file, glslshadermodeinfo[i].pretext);
1856                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1857                         FS_Print(file, shaderpermutationinfo[i].pretext);
1858                 FS_Print(file, "*/\n");
1859                 FS_Print(file, builtinshaderstring);
1860                 FS_Close(file);
1861                 Con_Printf("glsl/default.glsl written\n");
1862         }
1863         else
1864                 Con_Printf("failed to write to glsl/default.glsl\n");
1865
1866         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1867         if (file)
1868         {
1869                 FS_Print(file, "/* The engine may define the following macros:\n");
1870                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1871                 for (i = 0;i < SHADERMODE_COUNT;i++)
1872                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1873                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1874                         FS_Print(file, shaderpermutationinfo[i].pretext);
1875                 FS_Print(file, "*/\n");
1876                 FS_Print(file, builtinhlslshaderstring);
1877                 FS_Close(file);
1878                 Con_Printf("hlsl/default.hlsl written\n");
1879         }
1880         else
1881                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1882 }
1883
1884 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1885 {
1886         if (!second)
1887                 texturemode = GL_MODULATE;
1888         switch (vid.renderpath)
1889         {
1890         case RENDERPATH_D3D9:
1891 #ifdef SUPPORTD3D
1892                 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))));
1893                 R_Mesh_TexBind(GL20TU_FIRST , first );
1894                 R_Mesh_TexBind(GL20TU_SECOND, second);
1895 #endif
1896                 break;
1897         case RENDERPATH_D3D10:
1898                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1899                 break;
1900         case RENDERPATH_D3D11:
1901                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1902                 break;
1903         case RENDERPATH_GL20:
1904         case RENDERPATH_GLES2:
1905                 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))));
1906                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1907                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1908                 break;
1909         case RENDERPATH_GL13:
1910                 R_Mesh_TexBind(0, first );
1911                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1912                 R_Mesh_TexBind(1, second);
1913                 if (second)
1914                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1915                 break;
1916         case RENDERPATH_GL11:
1917                 R_Mesh_TexBind(0, first );
1918                 break;
1919         case RENDERPATH_SOFT:
1920                 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))));
1921                 R_Mesh_TexBind(GL20TU_FIRST , first );
1922                 R_Mesh_TexBind(GL20TU_SECOND, second);
1923                 break;
1924         }
1925 }
1926
1927 void R_SetupShader_DepthOrShadow(void)
1928 {
1929         switch (vid.renderpath)
1930         {
1931         case RENDERPATH_D3D9:
1932 #ifdef SUPPORTD3D
1933                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1934 #endif
1935                 break;
1936         case RENDERPATH_D3D10:
1937                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1938                 break;
1939         case RENDERPATH_D3D11:
1940                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1941                 break;
1942         case RENDERPATH_GL20:
1943         case RENDERPATH_GLES2:
1944                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1945                 break;
1946         case RENDERPATH_GL13:
1947                 R_Mesh_TexBind(0, 0);
1948                 R_Mesh_TexBind(1, 0);
1949                 break;
1950         case RENDERPATH_GL11:
1951                 R_Mesh_TexBind(0, 0);
1952                 break;
1953         case RENDERPATH_SOFT:
1954                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1955                 break;
1956         }
1957 }
1958
1959 void R_SetupShader_ShowDepth(void)
1960 {
1961         switch (vid.renderpath)
1962         {
1963         case RENDERPATH_D3D9:
1964 #ifdef SUPPORTHLSL
1965                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1966 #endif
1967                 break;
1968         case RENDERPATH_D3D10:
1969                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1970                 break;
1971         case RENDERPATH_D3D11:
1972                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1973                 break;
1974         case RENDERPATH_GL20:
1975         case RENDERPATH_GLES2:
1976                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1977                 break;
1978         case RENDERPATH_GL13:
1979                 break;
1980         case RENDERPATH_GL11:
1981                 break;
1982         case RENDERPATH_SOFT:
1983                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1984                 break;
1985         }
1986 }
1987
1988 extern qboolean r_shadow_usingdeferredprepass;
1989 extern cvar_t r_shadow_deferred_8bitrange;
1990 extern rtexture_t *r_shadow_attenuationgradienttexture;
1991 extern rtexture_t *r_shadow_attenuation2dtexture;
1992 extern rtexture_t *r_shadow_attenuation3dtexture;
1993 extern qboolean r_shadow_usingshadowmap2d;
1994 extern qboolean r_shadow_usingshadowmaportho;
1995 extern float r_shadow_shadowmap_texturescale[2];
1996 extern float r_shadow_shadowmap_parameters[4];
1997 extern qboolean r_shadow_shadowmapvsdct;
1998 extern qboolean r_shadow_shadowmapsampler;
1999 extern int r_shadow_shadowmappcf;
2000 extern rtexture_t *r_shadow_shadowmap2dtexture;
2001 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2002 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2003 extern matrix4x4_t r_shadow_shadowmapmatrix;
2004 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2005 extern int r_shadow_prepass_width;
2006 extern int r_shadow_prepass_height;
2007 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2008 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2009 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2010 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2011 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2012
2013 #define BLENDFUNC_ALLOWS_COLORMOD      1
2014 #define BLENDFUNC_ALLOWS_FOG           2
2015 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2016 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2017 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2018 static int R_BlendFuncFlags(int src, int dst)
2019 {
2020         int r = 0;
2021
2022         // a blendfunc allows colormod if:
2023         // a) it can never keep the destination pixel invariant, or
2024         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2025         // this is to prevent unintended side effects from colormod
2026
2027         // a blendfunc allows fog if:
2028         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2029         // this is to prevent unintended side effects from fog
2030
2031         // these checks are the output of fogeval.pl
2032
2033         r |= BLENDFUNC_ALLOWS_COLORMOD;
2034         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2035         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2036         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2037         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2038         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2039         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2040         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2041         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2042         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2043         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2044         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2045         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2046         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2047         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2048         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2049         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2050         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2051         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2052         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2053         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2054         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2055
2056         return r;
2057 }
2058
2059 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)
2060 {
2061         // select a permutation of the lighting shader appropriate to this
2062         // combination of texture, entity, light source, and fogging, only use the
2063         // minimum features necessary to avoid wasting rendering time in the
2064         // fragment shader on features that are not being used
2065         unsigned int permutation = 0;
2066         unsigned int mode = 0;
2067         int blendfuncflags;
2068         static float dummy_colormod[3] = {1, 1, 1};
2069         float *colormod = rsurface.colormod;
2070         float m16f[16];
2071         matrix4x4_t tempmatrix;
2072         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2073         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2074                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2075         if (rsurfacepass == RSURFPASS_BACKGROUND)
2076         {
2077                 // distorted background
2078                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2079                 {
2080                         mode = SHADERMODE_WATER;
2081                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2082                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2083                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2084                         {
2085                                 // this is the right thing to do for wateralpha
2086                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2087                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2088                         }
2089                         else
2090                         {
2091                                 // this is the right thing to do for entity alpha
2092                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2093                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2094                         }
2095                 }
2096                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2097                 {
2098                         mode = SHADERMODE_REFRACTION;
2099                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2100                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2101                 }
2102                 else
2103                 {
2104                         mode = SHADERMODE_GENERIC;
2105                         permutation |= SHADERPERMUTATION_DIFFUSE;
2106                         GL_BlendFunc(GL_ONE, GL_ZERO);
2107                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2108                 }
2109         }
2110         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2111         {
2112                 if (r_glsl_offsetmapping.integer)
2113                 {
2114                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2115                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2116                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2117                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2118                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2119                         {
2120                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2121                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2122                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2123                         }
2124                 }
2125                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2126                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2127                 // normalmap (deferred prepass), may use alpha test on diffuse
2128                 mode = SHADERMODE_DEFERREDGEOMETRY;
2129                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2130                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2131                 GL_BlendFunc(GL_ONE, GL_ZERO);
2132                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2133         }
2134         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2135         {
2136                 if (r_glsl_offsetmapping.integer)
2137                 {
2138                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2139                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2140                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2141                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2142                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2143                         {
2144                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2145                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2146                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2147                         }
2148                 }
2149                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2150                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2151                 // light source
2152                 mode = SHADERMODE_LIGHTSOURCE;
2153                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2154                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2155                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2156                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2157                 if (diffusescale > 0)
2158                         permutation |= SHADERPERMUTATION_DIFFUSE;
2159                 if (specularscale > 0)
2160                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2161                 if (r_refdef.fogenabled)
2162                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2163                 if (rsurface.texture->colormapping)
2164                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2165                 if (r_shadow_usingshadowmap2d)
2166                 {
2167                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2168                         if(r_shadow_shadowmapvsdct)
2169                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2170
2171                         if (r_shadow_shadowmapsampler)
2172                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2173                         if (r_shadow_shadowmappcf > 1)
2174                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2175                         else if (r_shadow_shadowmappcf)
2176                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2177                 }
2178                 if (rsurface.texture->reflectmasktexture)
2179                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2180                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2181                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2182         }
2183         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2184         {
2185                 if (r_glsl_offsetmapping.integer)
2186                 {
2187                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2188                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2189                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2190                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2191                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2192                         {
2193                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2194                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2195                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2196                         }
2197                 }
2198                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2199                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2200                 // unshaded geometry (fullbright or ambient model lighting)
2201                 mode = SHADERMODE_FLATCOLOR;
2202                 ambientscale = diffusescale = specularscale = 0;
2203                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2204                         permutation |= SHADERPERMUTATION_GLOW;
2205                 if (r_refdef.fogenabled)
2206                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2207                 if (rsurface.texture->colormapping)
2208                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2209                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2210                 {
2211                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2212                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2213
2214                         if (r_shadow_shadowmapsampler)
2215                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2216                         if (r_shadow_shadowmappcf > 1)
2217                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2218                         else if (r_shadow_shadowmappcf)
2219                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2220                 }
2221                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2222                         permutation |= SHADERPERMUTATION_REFLECTION;
2223                 if (rsurface.texture->reflectmasktexture)
2224                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2225                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2226                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2227         }
2228         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2229         {
2230                 if (r_glsl_offsetmapping.integer)
2231                 {
2232                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2233                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2234                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2235                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2236                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2237                         {
2238                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2239                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2240                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2241                         }
2242                 }
2243                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2244                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2245                 // directional model lighting
2246                 mode = SHADERMODE_LIGHTDIRECTION;
2247                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2248                         permutation |= SHADERPERMUTATION_GLOW;
2249                 permutation |= SHADERPERMUTATION_DIFFUSE;
2250                 if (specularscale > 0)
2251                         permutation |= SHADERPERMUTATION_SPECULAR;
2252                 if (r_refdef.fogenabled)
2253                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2254                 if (rsurface.texture->colormapping)
2255                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2256                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2257                 {
2258                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2259                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2260
2261                         if (r_shadow_shadowmapsampler)
2262                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2263                         if (r_shadow_shadowmappcf > 1)
2264                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2265                         else if (r_shadow_shadowmappcf)
2266                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2267                 }
2268                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2269                         permutation |= SHADERPERMUTATION_REFLECTION;
2270                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2271                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2272                 if (rsurface.texture->reflectmasktexture)
2273                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2274                 if (r_shadow_bouncegridtexture)
2275                 {
2276                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2277                         if (r_shadow_bouncegriddirectional)
2278                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2279                 }
2280                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2281                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2282         }
2283         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2284         {
2285                 if (r_glsl_offsetmapping.integer)
2286                 {
2287                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2288                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2289                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2290                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2291                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2292                         {
2293                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2294                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2295                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2296                         }
2297                 }
2298                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2299                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2300                 // ambient model lighting
2301                 mode = SHADERMODE_LIGHTDIRECTION;
2302                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2303                         permutation |= SHADERPERMUTATION_GLOW;
2304                 if (r_refdef.fogenabled)
2305                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2306                 if (rsurface.texture->colormapping)
2307                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2308                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2309                 {
2310                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2311                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2312
2313                         if (r_shadow_shadowmapsampler)
2314                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2315                         if (r_shadow_shadowmappcf > 1)
2316                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2317                         else if (r_shadow_shadowmappcf)
2318                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2319                 }
2320                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2321                         permutation |= SHADERPERMUTATION_REFLECTION;
2322                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2323                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2324                 if (rsurface.texture->reflectmasktexture)
2325                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2326                 if (r_shadow_bouncegridtexture)
2327                 {
2328                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2329                         if (r_shadow_bouncegriddirectional)
2330                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2331                 }
2332                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2333                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2334         }
2335         else
2336         {
2337                 if (r_glsl_offsetmapping.integer)
2338                 {
2339                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2340                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2341                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2342                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2343                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2344                         {
2345                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2346                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2347                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2348                         }
2349                 }
2350                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2351                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2352                 // lightmapped wall
2353                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2354                         permutation |= SHADERPERMUTATION_GLOW;
2355                 if (r_refdef.fogenabled)
2356                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2357                 if (rsurface.texture->colormapping)
2358                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2359                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2360                 {
2361                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2362                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2363
2364                         if (r_shadow_shadowmapsampler)
2365                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2366                         if (r_shadow_shadowmappcf > 1)
2367                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2368                         else if (r_shadow_shadowmappcf)
2369                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2370                 }
2371                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2372                         permutation |= SHADERPERMUTATION_REFLECTION;
2373                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2374                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2375                 if (rsurface.texture->reflectmasktexture)
2376                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2377                 if (FAKELIGHT_ENABLED)
2378                 {
2379                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2380                         mode = SHADERMODE_FAKELIGHT;
2381                         permutation |= SHADERPERMUTATION_DIFFUSE;
2382                         if (specularscale > 0)
2383                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2384                 }
2385                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2386                 {
2387                         // deluxemapping (light direction texture)
2388                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2389                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2390                         else
2391                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2392                         permutation |= SHADERPERMUTATION_DIFFUSE;
2393                         if (specularscale > 0)
2394                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2395                 }
2396                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2397                 {
2398                         // fake deluxemapping (uniform light direction in tangentspace)
2399                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2400                         permutation |= SHADERPERMUTATION_DIFFUSE;
2401                         if (specularscale > 0)
2402                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2403                 }
2404                 else if (rsurface.uselightmaptexture)
2405                 {
2406                         // ordinary lightmapping (q1bsp, q3bsp)
2407                         mode = SHADERMODE_LIGHTMAP;
2408                 }
2409                 else
2410                 {
2411                         // ordinary vertex coloring (q3bsp)
2412                         mode = SHADERMODE_VERTEXCOLOR;
2413                 }
2414                 if (r_shadow_bouncegridtexture)
2415                 {
2416                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2417                         if (r_shadow_bouncegriddirectional)
2418                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2419                 }
2420                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2422         }
2423         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2424                 colormod = dummy_colormod;
2425         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2426                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2427         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2428                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2429         switch(vid.renderpath)
2430         {
2431         case RENDERPATH_D3D9:
2432 #ifdef SUPPORTD3D
2433                 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);
2434                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2435                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2436                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2437                 if (mode == SHADERMODE_LIGHTSOURCE)
2438                 {
2439                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2440                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2441                 }
2442                 else
2443                 {
2444                         if (mode == SHADERMODE_LIGHTDIRECTION)
2445                         {
2446                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2447                         }
2448                 }
2449                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2450                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2451                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2452                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2453                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2454
2455                 if (mode == SHADERMODE_LIGHTSOURCE)
2456                 {
2457                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2458                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2459                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2460                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2461                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2462
2463                         // additive passes are only darkened by fog, not tinted
2464                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2465                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2466                 }
2467                 else
2468                 {
2469                         if (mode == SHADERMODE_FLATCOLOR)
2470                         {
2471                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2472                         }
2473                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2474                         {
2475                                 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]);
2476                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2477                                 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);
2478                                 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);
2479                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2480                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2481                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2482                         }
2483                         else
2484                         {
2485                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2486                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2487                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2488                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2489                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2490                         }
2491                         // additive passes are only darkened by fog, not tinted
2492                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2493                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2494                         else
2495                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2496                         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);
2497                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2498                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2499                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2500                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2501                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2502                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2503                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2504                         if (mode == SHADERMODE_WATER)
2505                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2506                 }
2507                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2508                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2509                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2510                 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));
2511                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2512                 if (rsurface.texture->pantstexture)
2513                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2514                 else
2515                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2516                 if (rsurface.texture->shirttexture)
2517                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2518                 else
2519                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2520                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2521                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2522                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2523                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2524                 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));
2525                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2526                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2527
2528                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2529                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2530                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2531                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2532                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2533                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2534                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2535                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2536                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2537                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2538                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2539                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2540                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2541                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2542                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2543                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2544                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2545                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2546                 {
2547                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2548                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2549                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2550                 }
2551                 else
2552                 {
2553                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2554                 }
2555 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2556 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2557                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2558                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2559                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2560                 {
2561                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2562                         if (rsurface.rtlight)
2563                         {
2564                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2565                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2566                         }
2567                 }
2568 #endif
2569                 break;
2570         case RENDERPATH_D3D10:
2571                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2572                 break;
2573         case RENDERPATH_D3D11:
2574                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2575                 break;
2576         case RENDERPATH_GL20:
2577         case RENDERPATH_GLES2:
2578                 if (!vid.useinterleavedarrays)
2579                 {
2580                         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);
2581                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2582                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2583                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2584                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2585                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2586                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2587                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2588                 }
2589                 else
2590                 {
2591                         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);
2592                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2593                 }
2594                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2595                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2596                 if (mode == SHADERMODE_LIGHTSOURCE)
2597                 {
2598                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2599                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2600                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2601                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2602                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2603                         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);
2604         
2605                         // additive passes are only darkened by fog, not tinted
2606                         if (r_glsl_permutation->loc_FogColor >= 0)
2607                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2608                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2609                 }
2610                 else
2611                 {
2612                         if (mode == SHADERMODE_FLATCOLOR)
2613                         {
2614                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2615                         }
2616                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2617                         {
2618                                 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]);
2619                                 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]);
2620                                 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);
2621                                 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);
2622                                 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);
2623                                 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]);
2624                                 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]);
2625                         }
2626                         else
2627                         {
2628                                 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]);
2629                                 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]);
2630                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2631                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2632                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2633                         }
2634                         // additive passes are only darkened by fog, not tinted
2635                         if (r_glsl_permutation->loc_FogColor >= 0)
2636                         {
2637                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2638                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2639                                 else
2640                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2641                         }
2642                         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);
2643                         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]);
2644                         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]);
2645                         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]);
2646                         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]);
2647                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2648                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2649                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2650                         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]);
2651                 }
2652                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2653                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2654                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2655                 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]);
2656                 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]);
2657
2658                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2659                 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));
2660                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2661                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2662                 {
2663                         if (rsurface.texture->pantstexture)
2664                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2665                         else
2666                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2667                 }
2668                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2669                 {
2670                         if (rsurface.texture->shirttexture)
2671                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2672                         else
2673                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2674                 }
2675                 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]);
2676                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2677                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2678                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2679                 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));
2680                 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]);
2681                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2682                 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);}
2683                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2684
2685                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2686                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2687                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2688                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2689                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2690                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2691                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2692                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2693                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2694                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2695                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2696                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2697                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2698                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2699                 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);
2700                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2701                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2702                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2703                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2704                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2705                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2706                 {
2707                         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);
2708                         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);
2709                         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);
2710                 }
2711                 else
2712                 {
2713                         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);
2714                 }
2715                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2716                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2717                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2718                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2719                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2720                 {
2721                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2722                         if (rsurface.rtlight)
2723                         {
2724                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2725                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2726                         }
2727                 }
2728                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2729                 CHECKGLERROR
2730                 break;
2731         case RENDERPATH_GL13:
2732         case RENDERPATH_GL11:
2733                 break;
2734         case RENDERPATH_SOFT:
2735                 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);
2736                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2737                 R_SetupShader_SetPermutationSoft(mode, permutation);
2738                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2739                 if (mode == SHADERMODE_LIGHTSOURCE)
2740                 {
2741                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2742                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2743                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2744                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2745                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2746                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2747         
2748                         // additive passes are only darkened by fog, not tinted
2749                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2750                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2751                 }
2752                 else
2753                 {
2754                         if (mode == SHADERMODE_FLATCOLOR)
2755                         {
2756                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2757                         }
2758                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2759                         {
2760                                 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]);
2761                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2762                                 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);
2763                                 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);
2764                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2765                                 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]);
2766                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2767                         }
2768                         else
2769                         {
2770                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2771                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2772                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2773                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2774                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2775                         }
2776                         // additive passes are only darkened by fog, not tinted
2777                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2778                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2779                         else
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2781                         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);
2782                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2783                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2784                         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]);
2785                         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]);
2786                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2787                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2788                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2789                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2790                 }
2791                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2792                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2793                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2794                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2795                 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]);
2796
2797                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2798                 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));
2799                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2800                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2801                 {
2802                         if (rsurface.texture->pantstexture)
2803                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2804                         else
2805                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2806                 }
2807                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2808                 {
2809                         if (rsurface.texture->shirttexture)
2810                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2811                         else
2812                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2813                 }
2814                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2815                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2816                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2817                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2818                 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));
2819                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2820                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2821
2822                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2823                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2824                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2825                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2826                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2827                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2828                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2829                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2830                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2831                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2832                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2833                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2834                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2835                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2836                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2837                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2838                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2839                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2840                 {
2841                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2842                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2843                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2844                 }
2845                 else
2846                 {
2847                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2848                 }
2849 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2850 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2851                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2852                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2853                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2854                 {
2855                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2856                         if (rsurface.rtlight)
2857                         {
2858                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2859                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2860                         }
2861                 }
2862                 break;
2863         }
2864 }
2865
2866 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2867 {
2868         // select a permutation of the lighting shader appropriate to this
2869         // combination of texture, entity, light source, and fogging, only use the
2870         // minimum features necessary to avoid wasting rendering time in the
2871         // fragment shader on features that are not being used
2872         unsigned int permutation = 0;
2873         unsigned int mode = 0;
2874         const float *lightcolorbase = rtlight->currentcolor;
2875         float ambientscale = rtlight->ambientscale;
2876         float diffusescale = rtlight->diffusescale;
2877         float specularscale = rtlight->specularscale;
2878         // this is the location of the light in view space
2879         vec3_t viewlightorigin;
2880         // this transforms from view space (camera) to light space (cubemap)
2881         matrix4x4_t viewtolight;
2882         matrix4x4_t lighttoview;
2883         float viewtolight16f[16];
2884         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2885         // light source
2886         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2887         if (rtlight->currentcubemap != r_texture_whitecube)
2888                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2889         if (diffusescale > 0)
2890                 permutation |= SHADERPERMUTATION_DIFFUSE;
2891         if (specularscale > 0)
2892                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2893         if (r_shadow_usingshadowmap2d)
2894         {
2895                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2896                 if (r_shadow_shadowmapvsdct)
2897                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2898
2899                 if (r_shadow_shadowmapsampler)
2900                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2901                 if (r_shadow_shadowmappcf > 1)
2902                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2903                 else if (r_shadow_shadowmappcf)
2904                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2905         }
2906         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2907         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2908         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2909         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2910         switch(vid.renderpath)
2911         {
2912         case RENDERPATH_D3D9:
2913 #ifdef SUPPORTD3D
2914                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2915                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2916                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2917                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2918                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2919                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2920                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2921                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2922                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2923                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2924                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2925
2926                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2927                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2928                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2929                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2930                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2931                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2932 #endif
2933                 break;
2934         case RENDERPATH_D3D10:
2935                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2936                 break;
2937         case RENDERPATH_D3D11:
2938                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2939                 break;
2940         case RENDERPATH_GL20:
2941         case RENDERPATH_GLES2:
2942                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2943                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2944                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2945                 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);
2946                 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);
2947                 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);
2948                 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]);
2949                 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]);
2950                 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));
2951                 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]);
2952                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2953
2954                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2955                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2956                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2957                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2958                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2959                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2960                 break;
2961         case RENDERPATH_GL13:
2962         case RENDERPATH_GL11:
2963                 break;
2964         case RENDERPATH_SOFT:
2965                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2966                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2967                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2968                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2969                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2970                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2971                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2972                 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]);
2973                 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));
2974                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2975                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2976
2977                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2978                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2979                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2980                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2981                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2982                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2983                 break;
2984         }
2985 }
2986
2987 #define SKINFRAME_HASH 1024
2988
2989 typedef struct
2990 {
2991         int loadsequence; // incremented each level change
2992         memexpandablearray_t array;
2993         skinframe_t *hash[SKINFRAME_HASH];
2994 }
2995 r_skinframe_t;
2996 r_skinframe_t r_skinframe;
2997
2998 void R_SkinFrame_PrepareForPurge(void)
2999 {
3000         r_skinframe.loadsequence++;
3001         // wrap it without hitting zero
3002         if (r_skinframe.loadsequence >= 200)
3003                 r_skinframe.loadsequence = 1;
3004 }
3005
3006 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3007 {
3008         if (!skinframe)
3009                 return;
3010         // mark the skinframe as used for the purging code
3011         skinframe->loadsequence = r_skinframe.loadsequence;
3012 }
3013
3014 void R_SkinFrame_Purge(void)
3015 {
3016         int i;
3017         skinframe_t *s;
3018         for (i = 0;i < SKINFRAME_HASH;i++)
3019         {
3020                 for (s = r_skinframe.hash[i];s;s = s->next)
3021                 {
3022                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3023                         {
3024                                 if (s->merged == s->base)
3025                                         s->merged = NULL;
3026                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3027                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3028                                 R_PurgeTexture(s->merged);s->merged = NULL;
3029                                 R_PurgeTexture(s->base  );s->base   = NULL;
3030                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3031                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3032                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3033                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3034                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3035                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3036                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3037                                 s->loadsequence = 0;
3038                         }
3039                 }
3040         }
3041 }
3042
3043 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3044         skinframe_t *item;
3045         char basename[MAX_QPATH];
3046
3047         Image_StripImageExtension(name, basename, sizeof(basename));
3048
3049         if( last == NULL ) {
3050                 int hashindex;
3051                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3052                 item = r_skinframe.hash[hashindex];
3053         } else {
3054                 item = last->next;
3055         }
3056
3057         // linearly search through the hash bucket
3058         for( ; item ; item = item->next ) {
3059                 if( !strcmp( item->basename, basename ) ) {
3060                         return item;
3061                 }
3062         }
3063         return NULL;
3064 }
3065
3066 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3067 {
3068         skinframe_t *item;
3069         int hashindex;
3070         char basename[MAX_QPATH];
3071
3072         Image_StripImageExtension(name, basename, sizeof(basename));
3073
3074         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3075         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3076                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3077                         break;
3078
3079         if (!item) {
3080                 rtexture_t *dyntexture;
3081                 // check whether its a dynamic texture
3082                 dyntexture = CL_GetDynTexture( basename );
3083                 if (!add && !dyntexture)
3084                         return NULL;
3085                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3086                 memset(item, 0, sizeof(*item));
3087                 strlcpy(item->basename, basename, sizeof(item->basename));
3088                 item->base = dyntexture; // either NULL or dyntexture handle
3089                 item->textureflags = textureflags;
3090                 item->comparewidth = comparewidth;
3091                 item->compareheight = compareheight;
3092                 item->comparecrc = comparecrc;
3093                 item->next = r_skinframe.hash[hashindex];
3094                 r_skinframe.hash[hashindex] = item;
3095         }
3096         else if( item->base == NULL )
3097         {
3098                 rtexture_t *dyntexture;
3099                 // check whether its a dynamic texture
3100                 // 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]
3101                 dyntexture = CL_GetDynTexture( basename );
3102                 item->base = dyntexture; // either NULL or dyntexture handle
3103         }
3104
3105         R_SkinFrame_MarkUsed(item);
3106         return item;
3107 }
3108
3109 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3110         { \
3111                 unsigned long long avgcolor[5], wsum; \
3112                 int pix, comp, w; \
3113                 avgcolor[0] = 0; \
3114                 avgcolor[1] = 0; \
3115                 avgcolor[2] = 0; \
3116                 avgcolor[3] = 0; \
3117                 avgcolor[4] = 0; \
3118                 wsum = 0; \
3119                 for(pix = 0; pix < cnt; ++pix) \
3120                 { \
3121                         w = 0; \
3122                         for(comp = 0; comp < 3; ++comp) \
3123                                 w += getpixel; \
3124                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3125                         { \
3126                                 ++wsum; \
3127                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3128                                 w = getpixel; \
3129                                 for(comp = 0; comp < 3; ++comp) \
3130                                         avgcolor[comp] += getpixel * w; \
3131                                 avgcolor[3] += w; \
3132                         } \
3133                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3134                         avgcolor[4] += getpixel; \
3135                 } \
3136                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3137                         avgcolor[3] = 1; \
3138                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3139                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3140                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3141                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3142         }
3143
3144 extern cvar_t gl_picmip;
3145 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3146 {
3147         int j;
3148         unsigned char *pixels;
3149         unsigned char *bumppixels;
3150         unsigned char *basepixels = NULL;
3151         int basepixels_width = 0;
3152         int basepixels_height = 0;
3153         skinframe_t *skinframe;
3154         rtexture_t *ddsbase = NULL;
3155         qboolean ddshasalpha = false;
3156         float ddsavgcolor[4];
3157         char basename[MAX_QPATH];
3158         int miplevel = R_PicmipForFlags(textureflags);
3159         int savemiplevel = miplevel;
3160         int mymiplevel;
3161
3162         if (cls.state == ca_dedicated)
3163                 return NULL;
3164
3165         // return an existing skinframe if already loaded
3166         // if loading of the first image fails, don't make a new skinframe as it
3167         // would cause all future lookups of this to be missing
3168         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3169         if (skinframe && skinframe->base)
3170                 return skinframe;
3171
3172         Image_StripImageExtension(name, basename, sizeof(basename));
3173
3174         // check for DDS texture file first
3175         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3176         {
3177                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3178                 if (basepixels == NULL)
3179                         return NULL;
3180         }
3181
3182         // FIXME handle miplevel
3183
3184         if (developer_loading.integer)
3185                 Con_Printf("loading skin \"%s\"\n", name);
3186
3187         // we've got some pixels to store, so really allocate this new texture now
3188         if (!skinframe)
3189                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3190         skinframe->stain = NULL;
3191         skinframe->merged = NULL;
3192         skinframe->base = NULL;
3193         skinframe->pants = NULL;
3194         skinframe->shirt = NULL;
3195         skinframe->nmap = NULL;
3196         skinframe->gloss = NULL;
3197         skinframe->glow = NULL;
3198         skinframe->fog = NULL;
3199         skinframe->reflect = NULL;
3200         skinframe->hasalpha = false;
3201
3202         if (ddsbase)
3203         {
3204                 skinframe->base = ddsbase;
3205                 skinframe->hasalpha = ddshasalpha;
3206                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3207                 if (r_loadfog && skinframe->hasalpha)
3208                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3209                 //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]);
3210         }
3211         else
3212         {
3213                 basepixels_width = image_width;
3214                 basepixels_height = image_height;
3215                 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);
3216                 if (textureflags & TEXF_ALPHA)
3217                 {
3218                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3219                         {
3220                                 if (basepixels[j] < 255)
3221                                 {
3222                                         skinframe->hasalpha = true;
3223                                         break;
3224                                 }
3225                         }
3226                         if (r_loadfog && skinframe->hasalpha)
3227                         {
3228                                 // has transparent pixels
3229                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3230                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3231                                 {
3232                                         pixels[j+0] = 255;
3233                                         pixels[j+1] = 255;
3234                                         pixels[j+2] = 255;
3235                                         pixels[j+3] = basepixels[j+3];
3236                                 }
3237                                 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);
3238                                 Mem_Free(pixels);
3239                         }
3240                 }
3241                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3242                 //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]);
3243                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3244                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3245                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3246                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3247         }
3248
3249         if (r_loaddds)
3250         {
3251                 mymiplevel = savemiplevel;
3252                 if (r_loadnormalmap)
3253                         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);
3254                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3255                 if (r_loadgloss)
3256                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3257                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3258                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3259                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3260         }
3261
3262         // _norm is the name used by tenebrae and has been adopted as standard
3263         if (r_loadnormalmap && skinframe->nmap == NULL)
3264         {
3265                 mymiplevel = savemiplevel;
3266                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3267                 {
3268                         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);
3269                         Mem_Free(pixels);
3270                         pixels = NULL;
3271                 }
3272                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3273                 {
3274                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3275                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3276                         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);
3277                         Mem_Free(pixels);
3278                         Mem_Free(bumppixels);
3279                 }
3280                 else if (r_shadow_bumpscale_basetexture.value > 0)
3281                 {
3282                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3283                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3284                         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);
3285                         Mem_Free(pixels);
3286                 }
3287                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3288                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3289         }
3290
3291         // _luma is supported only for tenebrae compatibility
3292         // _glow is the preferred name
3293         mymiplevel = savemiplevel;
3294         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))))
3295         {
3296                 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);
3297                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3298                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3299                 Mem_Free(pixels);pixels = NULL;
3300         }
3301
3302         mymiplevel = savemiplevel;
3303         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3304         {
3305                 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);
3306                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3307                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3308                 Mem_Free(pixels);
3309                 pixels = NULL;
3310         }
3311
3312         mymiplevel = savemiplevel;
3313         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3314         {
3315                 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);
3316                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3317                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3318                 Mem_Free(pixels);
3319                 pixels = NULL;
3320         }
3321
3322         mymiplevel = savemiplevel;
3323         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3324         {
3325                 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);
3326                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3327                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3328                 Mem_Free(pixels);
3329                 pixels = NULL;
3330         }
3331
3332         mymiplevel = savemiplevel;
3333         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3334         {
3335                 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);
3336                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3337                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3338                 Mem_Free(pixels);
3339                 pixels = NULL;
3340         }
3341
3342         if (basepixels)
3343                 Mem_Free(basepixels);
3344
3345         return skinframe;
3346 }
3347
3348 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3349 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3350 {
3351         int i;
3352         unsigned char *temp1, *temp2;
3353         skinframe_t *skinframe;
3354
3355         if (cls.state == ca_dedicated)
3356                 return NULL;
3357
3358         // if already loaded just return it, otherwise make a new skinframe
3359         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3360         if (skinframe && skinframe->base)
3361                 return skinframe;
3362
3363         skinframe->stain = NULL;
3364         skinframe->merged = NULL;
3365         skinframe->base = NULL;
3366         skinframe->pants = NULL;
3367         skinframe->shirt = NULL;
3368         skinframe->nmap = NULL;
3369         skinframe->gloss = NULL;
3370         skinframe->glow = NULL;
3371         skinframe->fog = NULL;
3372         skinframe->reflect = NULL;
3373         skinframe->hasalpha = false;
3374
3375         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3376         if (!skindata)
3377                 return NULL;
3378
3379         if (developer_loading.integer)
3380                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3381
3382         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3383         {
3384                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3385                 temp2 = temp1 + width * height * 4;
3386                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3387                 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);
3388                 Mem_Free(temp1);
3389         }
3390         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3391         if (textureflags & TEXF_ALPHA)
3392         {
3393                 for (i = 3;i < width * height * 4;i += 4)
3394                 {
3395                         if (skindata[i] < 255)
3396                         {
3397                                 skinframe->hasalpha = true;
3398                                 break;
3399                         }
3400                 }
3401                 if (r_loadfog && skinframe->hasalpha)
3402                 {
3403                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3404                         memcpy(fogpixels, skindata, width * height * 4);
3405                         for (i = 0;i < width * height * 4;i += 4)
3406                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3407                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3408                         Mem_Free(fogpixels);
3409                 }
3410         }
3411
3412         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3413         //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]);
3414
3415         return skinframe;
3416 }
3417
3418 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3419 {
3420         int i;
3421         int featuresmask;
3422         skinframe_t *skinframe;
3423
3424         if (cls.state == ca_dedicated)
3425                 return NULL;
3426
3427         // if already loaded just return it, otherwise make a new skinframe
3428         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3429         if (skinframe && skinframe->base)
3430                 return skinframe;
3431
3432         skinframe->stain = NULL;
3433         skinframe->merged = NULL;
3434         skinframe->base = NULL;
3435         skinframe->pants = NULL;
3436         skinframe->shirt = NULL;
3437         skinframe->nmap = NULL;
3438         skinframe->gloss = NULL;
3439         skinframe->glow = NULL;
3440         skinframe->fog = NULL;
3441         skinframe->reflect = NULL;
3442         skinframe->hasalpha = false;
3443
3444         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3445         if (!skindata)
3446                 return NULL;
3447
3448         if (developer_loading.integer)
3449                 Con_Printf("loading quake skin \"%s\"\n", name);
3450
3451         // 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)
3452         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3453         memcpy(skinframe->qpixels, skindata, width*height);
3454         skinframe->qwidth = width;
3455         skinframe->qheight = height;
3456
3457         featuresmask = 0;
3458         for (i = 0;i < width * height;i++)
3459                 featuresmask |= palette_featureflags[skindata[i]];
3460
3461         skinframe->hasalpha = false;
3462         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3463         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3464         skinframe->qgeneratemerged = true;
3465         skinframe->qgeneratebase = skinframe->qhascolormapping;
3466         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3467
3468         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3469         //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]);
3470
3471         return skinframe;
3472 }
3473
3474 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3475 {
3476         int width;
3477         int height;
3478         unsigned char *skindata;
3479
3480         if (!skinframe->qpixels)
3481                 return;
3482
3483         if (!skinframe->qhascolormapping)
3484                 colormapped = false;
3485
3486         if (colormapped)
3487         {
3488                 if (!skinframe->qgeneratebase)
3489                         return;
3490         }
3491         else
3492         {
3493                 if (!skinframe->qgeneratemerged)
3494                         return;
3495         }
3496
3497         width = skinframe->qwidth;
3498         height = skinframe->qheight;
3499         skindata = skinframe->qpixels;
3500
3501         if (skinframe->qgeneratenmap)
3502         {
3503                 unsigned char *temp1, *temp2;
3504                 skinframe->qgeneratenmap = false;
3505                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3506                 temp2 = temp1 + width * height * 4;
3507                 // use either a custom palette or the quake palette
3508                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3509                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3510                 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);
3511                 Mem_Free(temp1);
3512         }
3513
3514         if (skinframe->qgenerateglow)
3515         {
3516                 skinframe->qgenerateglow = false;
3517                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3518         }
3519
3520         if (colormapped)
3521         {
3522                 skinframe->qgeneratebase = false;
3523                 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);
3524                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3525                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3526         }
3527         else
3528         {
3529                 skinframe->qgeneratemerged = false;
3530                 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);
3531         }
3532
3533         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3534         {
3535                 Mem_Free(skinframe->qpixels);
3536                 skinframe->qpixels = NULL;
3537         }
3538 }
3539
3540 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)
3541 {
3542         int i;
3543         skinframe_t *skinframe;
3544
3545         if (cls.state == ca_dedicated)
3546                 return NULL;
3547
3548         // if already loaded just return it, otherwise make a new skinframe
3549         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3550         if (skinframe && skinframe->base)
3551                 return skinframe;
3552
3553         skinframe->stain = NULL;
3554         skinframe->merged = NULL;
3555         skinframe->base = NULL;
3556         skinframe->pants = NULL;
3557         skinframe->shirt = NULL;
3558         skinframe->nmap = NULL;
3559         skinframe->gloss = NULL;
3560         skinframe->glow = NULL;
3561         skinframe->fog = NULL;
3562         skinframe->reflect = NULL;
3563         skinframe->hasalpha = false;
3564
3565         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3566         if (!skindata)
3567                 return NULL;
3568
3569         if (developer_loading.integer)
3570                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3571
3572         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3573         if (textureflags & TEXF_ALPHA)
3574         {
3575                 for (i = 0;i < width * height;i++)
3576                 {
3577                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3578                         {
3579                                 skinframe->hasalpha = true;
3580                                 break;
3581                         }
3582                 }
3583                 if (r_loadfog && skinframe->hasalpha)
3584                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3585         }
3586
3587         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3588         //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]);
3589
3590         return skinframe;
3591 }
3592
3593 skinframe_t *R_SkinFrame_LoadMissing(void)
3594 {
3595         skinframe_t *skinframe;
3596
3597         if (cls.state == ca_dedicated)
3598                 return NULL;
3599
3600         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3601         skinframe->stain = NULL;
3602         skinframe->merged = NULL;
3603         skinframe->base = NULL;
3604         skinframe->pants = NULL;
3605         skinframe->shirt = NULL;
3606         skinframe->nmap = NULL;
3607         skinframe->gloss = NULL;
3608         skinframe->glow = NULL;
3609         skinframe->fog = NULL;
3610         skinframe->reflect = NULL;
3611         skinframe->hasalpha = false;
3612
3613         skinframe->avgcolor[0] = rand() / RAND_MAX;
3614         skinframe->avgcolor[1] = rand() / RAND_MAX;
3615         skinframe->avgcolor[2] = rand() / RAND_MAX;
3616         skinframe->avgcolor[3] = 1;
3617
3618         return skinframe;
3619 }
3620
3621 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3622 typedef struct suffixinfo_s
3623 {
3624         const char *suffix;
3625         qboolean flipx, flipy, flipdiagonal;
3626 }
3627 suffixinfo_t;
3628 static suffixinfo_t suffix[3][6] =
3629 {
3630         {
3631                 {"px",   false, false, false},
3632                 {"nx",   false, false, false},
3633                 {"py",   false, false, false},
3634                 {"ny",   false, false, false},
3635                 {"pz",   false, false, false},
3636                 {"nz",   false, false, false}
3637         },
3638         {
3639                 {"posx", false, false, false},
3640                 {"negx", false, false, false},
3641                 {"posy", false, false, false},
3642                 {"negy", false, false, false},
3643                 {"posz", false, false, false},
3644                 {"negz", false, false, false}
3645         },
3646         {
3647                 {"rt",    true, false,  true},
3648                 {"lf",   false,  true,  true},
3649                 {"ft",    true,  true, false},
3650                 {"bk",   false, false, false},
3651                 {"up",    true, false,  true},
3652                 {"dn",    true, false,  true}
3653         }
3654 };
3655
3656 static int componentorder[4] = {0, 1, 2, 3};
3657
3658 rtexture_t *R_LoadCubemap(const char *basename)
3659 {
3660         int i, j, cubemapsize;
3661         unsigned char *cubemappixels, *image_buffer;
3662         rtexture_t *cubemaptexture;
3663         char name[256];
3664         // must start 0 so the first loadimagepixels has no requested width/height
3665         cubemapsize = 0;
3666         cubemappixels = NULL;
3667         cubemaptexture = NULL;
3668         // keep trying different suffix groups (posx, px, rt) until one loads
3669         for (j = 0;j < 3 && !cubemappixels;j++)
3670         {
3671                 // load the 6 images in the suffix group
3672                 for (i = 0;i < 6;i++)
3673                 {
3674                         // generate an image name based on the base and and suffix
3675                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3676                         // load it
3677                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3678                         {
3679                                 // an image loaded, make sure width and height are equal
3680                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3681                                 {
3682                                         // if this is the first image to load successfully, allocate the cubemap memory
3683                                         if (!cubemappixels && image_width >= 1)
3684                                         {
3685                                                 cubemapsize = image_width;
3686                                                 // note this clears to black, so unavailable sides are black
3687                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3688                                         }
3689                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3690                                         if (cubemappixels)
3691                                                 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);
3692                                 }
3693                                 else
3694                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3695                                 // free the image
3696                                 Mem_Free(image_buffer);
3697                         }
3698                 }
3699         }
3700         // if a cubemap loaded, upload it
3701         if (cubemappixels)
3702         {
3703                 if (developer_loading.integer)
3704                         Con_Printf("loading cubemap \"%s\"\n", basename);
3705
3706                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3707                 Mem_Free(cubemappixels);
3708         }
3709         else
3710         {
3711                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3712                 if (developer_loading.integer)
3713                 {
3714                         Con_Printf("(tried tried images ");
3715                         for (j = 0;j < 3;j++)
3716                                 for (i = 0;i < 6;i++)
3717                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3718                         Con_Print(" and was unable to find any of them).\n");
3719                 }
3720         }
3721         return cubemaptexture;
3722 }
3723
3724 rtexture_t *R_GetCubemap(const char *basename)
3725 {
3726         int i;
3727         for (i = 0;i < r_texture_numcubemaps;i++)
3728                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3729                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3730         if (i >= MAX_CUBEMAPS)
3731                 return r_texture_whitecube;
3732         r_texture_numcubemaps++;
3733         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3734         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3735         return r_texture_cubemaps[i].texture;
3736 }
3737
3738 void R_FreeCubemaps(void)
3739 {
3740         int i;
3741         for (i = 0;i < r_texture_numcubemaps;i++)
3742         {
3743                 if (developer_loading.integer)
3744                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3745                 if (r_texture_cubemaps[i].texture)
3746                         R_FreeTexture(r_texture_cubemaps[i].texture);
3747         }
3748         r_texture_numcubemaps = 0;
3749 }
3750
3751 void R_Main_FreeViewCache(void)
3752 {
3753         if (r_refdef.viewcache.entityvisible)
3754                 Mem_Free(r_refdef.viewcache.entityvisible);
3755         if (r_refdef.viewcache.world_pvsbits)
3756                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3757         if (r_refdef.viewcache.world_leafvisible)
3758                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3759         if (r_refdef.viewcache.world_surfacevisible)
3760                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3761         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3762 }
3763
3764 void R_Main_ResizeViewCache(void)
3765 {
3766         int numentities = r_refdef.scene.numentities;
3767         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3768         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3769         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3770         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3771         if (r_refdef.viewcache.maxentities < numentities)
3772         {
3773                 r_refdef.viewcache.maxentities = numentities;
3774                 if (r_refdef.viewcache.entityvisible)
3775                         Mem_Free(r_refdef.viewcache.entityvisible);
3776                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3777         }
3778         if (r_refdef.viewcache.world_numclusters != numclusters)
3779         {
3780                 r_refdef.viewcache.world_numclusters = numclusters;
3781                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3782                 if (r_refdef.viewcache.world_pvsbits)
3783                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3784                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3785         }
3786         if (r_refdef.viewcache.world_numleafs != numleafs)
3787         {
3788                 r_refdef.viewcache.world_numleafs = numleafs;
3789                 if (r_refdef.viewcache.world_leafvisible)
3790                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3791                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3792         }
3793         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3794         {
3795                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3796                 if (r_refdef.viewcache.world_surfacevisible)
3797                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3798                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3799         }
3800 }
3801
3802 extern rtexture_t *loadingscreentexture;
3803 void gl_main_start(void)
3804 {
3805         loadingscreentexture = NULL;
3806         r_texture_blanknormalmap = NULL;
3807         r_texture_white = NULL;
3808         r_texture_grey128 = NULL;
3809         r_texture_black = NULL;
3810         r_texture_whitecube = NULL;
3811         r_texture_normalizationcube = NULL;
3812         r_texture_fogattenuation = NULL;
3813         r_texture_fogheighttexture = NULL;
3814         r_texture_gammaramps = NULL;
3815         r_texture_numcubemaps = 0;
3816
3817         r_loaddds = r_texture_dds_load.integer != 0;
3818         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3819
3820         switch(vid.renderpath)
3821         {
3822         case RENDERPATH_GL20:
3823         case RENDERPATH_D3D9:
3824         case RENDERPATH_D3D10:
3825         case RENDERPATH_D3D11:
3826         case RENDERPATH_SOFT:
3827                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3828                 Cvar_SetValueQuick(&gl_combine, 1);
3829                 Cvar_SetValueQuick(&r_glsl, 1);
3830                 r_loadnormalmap = true;
3831                 r_loadgloss = true;
3832                 r_loadfog = false;
3833                 break;
3834         case RENDERPATH_GL13:
3835                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3836                 Cvar_SetValueQuick(&gl_combine, 1);
3837                 Cvar_SetValueQuick(&r_glsl, 0);
3838                 r_loadnormalmap = false;
3839                 r_loadgloss = false;
3840                 r_loadfog = true;
3841                 break;
3842         case RENDERPATH_GL11:
3843                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3844                 Cvar_SetValueQuick(&gl_combine, 0);
3845                 Cvar_SetValueQuick(&r_glsl, 0);
3846                 r_loadnormalmap = false;
3847                 r_loadgloss = false;
3848                 r_loadfog = true;
3849                 break;
3850         case RENDERPATH_GLES2:
3851                 Cvar_SetValueQuick(&r_textureunits, 1);
3852                 Cvar_SetValueQuick(&gl_combine, 1);
3853                 Cvar_SetValueQuick(&r_glsl, 1);
3854                 r_loadnormalmap = true;
3855                 r_loadgloss = false;
3856                 r_loadfog = false;
3857                 break;
3858         }
3859
3860         R_AnimCache_Free();
3861         R_FrameData_Reset();
3862
3863         r_numqueries = 0;
3864         r_maxqueries = 0;
3865         memset(r_queries, 0, sizeof(r_queries));
3866
3867         r_qwskincache = NULL;
3868         r_qwskincache_size = 0;
3869
3870         // due to caching of texture_t references, the collision cache must be reset
3871         Collision_Cache_Reset(true);
3872
3873         // set up r_skinframe loading system for textures
3874         memset(&r_skinframe, 0, sizeof(r_skinframe));
3875         r_skinframe.loadsequence = 1;
3876         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3877
3878         r_main_texturepool = R_AllocTexturePool();
3879         R_BuildBlankTextures();
3880         R_BuildNoTexture();
3881         if (vid.support.arb_texture_cube_map)
3882         {
3883                 R_BuildWhiteCube();
3884                 R_BuildNormalizationCube();
3885         }
3886         r_texture_fogattenuation = NULL;
3887         r_texture_fogheighttexture = NULL;
3888         r_texture_gammaramps = NULL;
3889         //r_texture_fogintensity = NULL;
3890         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3891         memset(&r_waterstate, 0, sizeof(r_waterstate));
3892         r_glsl_permutation = NULL;
3893         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3894         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3895         glslshaderstring = NULL;
3896 #ifdef SUPPORTD3D
3897         r_hlsl_permutation = NULL;
3898         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3899         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3900 #endif
3901         hlslshaderstring = NULL;
3902         memset(&r_svbsp, 0, sizeof (r_svbsp));
3903
3904         r_refdef.fogmasktable_density = 0;
3905 }
3906
3907 void gl_main_shutdown(void)
3908 {
3909         R_AnimCache_Free();
3910         R_FrameData_Reset();
3911
3912         R_Main_FreeViewCache();
3913
3914         switch(vid.renderpath)
3915         {
3916         case RENDERPATH_GL11:
3917         case RENDERPATH_GL13:
3918         case RENDERPATH_GL20:
3919         case RENDERPATH_GLES2:
3920                 if (r_maxqueries)
3921                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3922                 break;
3923         case RENDERPATH_D3D9:
3924                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3925                 break;
3926         case RENDERPATH_D3D10:
3927                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3928                 break;
3929         case RENDERPATH_D3D11:
3930                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3931                 break;
3932         case RENDERPATH_SOFT:
3933                 break;
3934         }
3935
3936         r_numqueries = 0;
3937         r_maxqueries = 0;
3938         memset(r_queries, 0, sizeof(r_queries));
3939
3940         r_qwskincache = NULL;
3941         r_qwskincache_size = 0;
3942
3943         // clear out the r_skinframe state
3944         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3945         memset(&r_skinframe, 0, sizeof(r_skinframe));
3946
3947         if (r_svbsp.nodes)
3948                 Mem_Free(r_svbsp.nodes);
3949         memset(&r_svbsp, 0, sizeof (r_svbsp));
3950         R_FreeTexturePool(&r_main_texturepool);
3951         loadingscreentexture = NULL;
3952         r_texture_blanknormalmap = NULL;
3953         r_texture_white = NULL;
3954         r_texture_grey128 = NULL;
3955         r_texture_black = NULL;
3956         r_texture_whitecube = NULL;
3957         r_texture_normalizationcube = NULL;
3958         r_texture_fogattenuation = NULL;
3959         r_texture_fogheighttexture = NULL;
3960         r_texture_gammaramps = NULL;
3961         r_texture_numcubemaps = 0;
3962         //r_texture_fogintensity = NULL;
3963         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3964         memset(&r_waterstate, 0, sizeof(r_waterstate));
3965         R_GLSL_Restart_f();
3966
3967         r_glsl_permutation = NULL;
3968         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3969         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3970         glslshaderstring = NULL;
3971 #ifdef SUPPORTD3D
3972         r_hlsl_permutation = NULL;
3973         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3974         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3975 #endif
3976         hlslshaderstring = NULL;
3977 }
3978
3979 extern void CL_ParseEntityLump(char *entitystring);
3980 void gl_main_newmap(void)
3981 {
3982         // FIXME: move this code to client
3983         char *entities, entname[MAX_QPATH];
3984         if (r_qwskincache)
3985                 Mem_Free(r_qwskincache);
3986         r_qwskincache = NULL;
3987         r_qwskincache_size = 0;
3988         if (cl.worldmodel)
3989         {
3990                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3991                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3992                 {
3993                         CL_ParseEntityLump(entities);
3994                         Mem_Free(entities);
3995                         return;
3996                 }
3997                 if (cl.worldmodel->brush.entities)
3998                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3999         }
4000         R_Main_FreeViewCache();
4001
4002         R_FrameData_Reset();
4003 }
4004
4005 void GL_Main_Init(void)
4006 {
4007         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4008
4009         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4010         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4011         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4012         if (gamemode == GAME_NEHAHRA)
4013         {
4014                 Cvar_RegisterVariable (&gl_fogenable);
4015                 Cvar_RegisterVariable (&gl_fogdensity);
4016                 Cvar_RegisterVariable (&gl_fogred);
4017                 Cvar_RegisterVariable (&gl_foggreen);
4018                 Cvar_RegisterVariable (&gl_fogblue);
4019                 Cvar_RegisterVariable (&gl_fogstart);
4020                 Cvar_RegisterVariable (&gl_fogend);
4021                 Cvar_RegisterVariable (&gl_skyclip);
4022         }
4023         Cvar_RegisterVariable(&r_motionblur);
4024         Cvar_RegisterVariable(&r_motionblur_maxblur);
4025         Cvar_RegisterVariable(&r_motionblur_bmin);
4026         Cvar_RegisterVariable(&r_motionblur_vmin);
4027         Cvar_RegisterVariable(&r_motionblur_vmax);
4028         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4029         Cvar_RegisterVariable(&r_motionblur_randomize);
4030         Cvar_RegisterVariable(&r_damageblur);
4031         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4032         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4033         Cvar_RegisterVariable(&r_equalize_entities_by);
4034         Cvar_RegisterVariable(&r_equalize_entities_to);
4035         Cvar_RegisterVariable(&r_depthfirst);
4036         Cvar_RegisterVariable(&r_useinfinitefarclip);
4037         Cvar_RegisterVariable(&r_farclip_base);
4038         Cvar_RegisterVariable(&r_farclip_world);
4039         Cvar_RegisterVariable(&r_nearclip);
4040         Cvar_RegisterVariable(&r_showbboxes);
4041         Cvar_RegisterVariable(&r_showsurfaces);
4042         Cvar_RegisterVariable(&r_showtris);
4043         Cvar_RegisterVariable(&r_shownormals);
4044         Cvar_RegisterVariable(&r_showlighting);
4045         Cvar_RegisterVariable(&r_showshadowvolumes);
4046         Cvar_RegisterVariable(&r_showcollisionbrushes);
4047         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4048         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4049         Cvar_RegisterVariable(&r_showdisabledepthtest);
4050         Cvar_RegisterVariable(&r_drawportals);
4051         Cvar_RegisterVariable(&r_drawentities);
4052         Cvar_RegisterVariable(&r_draw2d);
4053         Cvar_RegisterVariable(&r_drawworld);
4054         Cvar_RegisterVariable(&r_cullentities_trace);
4055         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4056         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4057         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4058         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4059         Cvar_RegisterVariable(&r_drawviewmodel);
4060         Cvar_RegisterVariable(&r_drawexteriormodel);
4061         Cvar_RegisterVariable(&r_speeds);
4062         Cvar_RegisterVariable(&r_fullbrights);
4063         Cvar_RegisterVariable(&r_wateralpha);
4064         Cvar_RegisterVariable(&r_dynamic);
4065         Cvar_RegisterVariable(&r_fakelight);
4066         Cvar_RegisterVariable(&r_fakelight_intensity);
4067         Cvar_RegisterVariable(&r_fullbright);
4068         Cvar_RegisterVariable(&r_shadows);
4069         Cvar_RegisterVariable(&r_shadows_darken);
4070         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4071         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4072         Cvar_RegisterVariable(&r_shadows_throwdistance);
4073         Cvar_RegisterVariable(&r_shadows_throwdirection);
4074         Cvar_RegisterVariable(&r_shadows_focus);
4075         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4076         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4077         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4078         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4079         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4080         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4081         Cvar_RegisterVariable(&r_fog_exp2);
4082         Cvar_RegisterVariable(&r_fog_clear);
4083         Cvar_RegisterVariable(&r_drawfog);
4084         Cvar_RegisterVariable(&r_transparentdepthmasking);
4085         Cvar_RegisterVariable(&r_texture_dds_load);
4086         Cvar_RegisterVariable(&r_texture_dds_save);
4087         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4088         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4089         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4090         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4091         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4092         Cvar_RegisterVariable(&r_textureunits);
4093         Cvar_RegisterVariable(&gl_combine);
4094         Cvar_RegisterVariable(&r_glsl);
4095         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4096         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4097         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4098         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4099         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4100         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4101         Cvar_RegisterVariable(&r_glsl_postprocess);
4102         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4103         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4104         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4105         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4106         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4107         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4108         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4109         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4110
4111         Cvar_RegisterVariable(&r_water);
4112         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4113         Cvar_RegisterVariable(&r_water_clippingplanebias);
4114         Cvar_RegisterVariable(&r_water_refractdistort);
4115         Cvar_RegisterVariable(&r_water_reflectdistort);
4116         Cvar_RegisterVariable(&r_water_scissormode);
4117         Cvar_RegisterVariable(&r_lerpsprites);
4118         Cvar_RegisterVariable(&r_lerpmodels);
4119         Cvar_RegisterVariable(&r_lerplightstyles);
4120         Cvar_RegisterVariable(&r_waterscroll);
4121         Cvar_RegisterVariable(&r_bloom);
4122         Cvar_RegisterVariable(&r_bloom_colorscale);
4123         Cvar_RegisterVariable(&r_bloom_brighten);
4124         Cvar_RegisterVariable(&r_bloom_blur);
4125         Cvar_RegisterVariable(&r_bloom_resolution);
4126         Cvar_RegisterVariable(&r_bloom_colorexponent);
4127         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4128         Cvar_RegisterVariable(&r_hdr);
4129         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4130         Cvar_RegisterVariable(&r_hdr_glowintensity);
4131         Cvar_RegisterVariable(&r_hdr_range);
4132         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4133         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4134         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4135         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4136         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4137         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4138         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4139         Cvar_RegisterVariable(&developer_texturelogging);
4140         Cvar_RegisterVariable(&gl_lightmaps);
4141         Cvar_RegisterVariable(&r_test);
4142         Cvar_RegisterVariable(&r_glsl_saturation);
4143         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4144         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4145         Cvar_RegisterVariable(&r_framedatasize);
4146         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4147                 Cvar_SetValue("r_fullbrights", 0);
4148         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4149
4150         Cvar_RegisterVariable(&r_track_sprites);
4151         Cvar_RegisterVariable(&r_track_sprites_flags);
4152         Cvar_RegisterVariable(&r_track_sprites_scalew);
4153         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4154         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4155         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4156         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4157         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4158 }
4159
4160 extern void R_Textures_Init(void);
4161 extern void GL_Draw_Init(void);
4162 extern void GL_Main_Init(void);
4163 extern void R_Shadow_Init(void);
4164 extern void R_Sky_Init(void);
4165 extern void GL_Surf_Init(void);
4166 extern void R_Particles_Init(void);
4167 extern void R_Explosion_Init(void);
4168 extern void gl_backend_init(void);
4169 extern void Sbar_Init(void);
4170 extern void R_LightningBeams_Init(void);
4171 extern void Mod_RenderInit(void);
4172 extern void Font_Init(void);
4173
4174 void Render_Init(void)
4175 {
4176         gl_backend_init();
4177         R_Textures_Init();
4178         GL_Main_Init();
4179         Font_Init();
4180         GL_Draw_Init();
4181         R_Shadow_Init();
4182         R_Sky_Init();
4183         GL_Surf_Init();
4184         Sbar_Init();
4185         R_Particles_Init();
4186         R_Explosion_Init();
4187         R_LightningBeams_Init();
4188         Mod_RenderInit();
4189 }
4190
4191 /*
4192 ===============
4193 GL_Init
4194 ===============
4195 */
4196 extern char *ENGINE_EXTENSIONS;
4197 void GL_Init (void)
4198 {
4199         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4200         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4201         gl_version = (const char *)qglGetString(GL_VERSION);
4202         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4203
4204         if (!gl_extensions)
4205                 gl_extensions = "";
4206         if (!gl_platformextensions)
4207                 gl_platformextensions = "";
4208
4209         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4210         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4211         Con_Printf("GL_VERSION: %s\n", gl_version);
4212         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4213         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4214
4215         VID_CheckExtensions();
4216
4217         // LordHavoc: report supported extensions
4218         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4219
4220         // clear to black (loading plaque will be seen over this)
4221         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4222 }
4223
4224 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4225 {
4226         int i;
4227         mplane_t *p;
4228         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4229         {
4230                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4231                 if (i == 4)
4232                         continue;
4233                 p = r_refdef.view.frustum + i;
4234                 switch(p->signbits)
4235                 {
4236                 default:
4237                 case 0:
4238                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4239                                 return true;
4240                         break;
4241                 case 1:
4242                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4243                                 return true;
4244                         break;
4245                 case 2:
4246                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4247                                 return true;
4248                         break;
4249                 case 3:
4250                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4251                                 return true;
4252                         break;
4253                 case 4:
4254                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4255                                 return true;
4256                         break;
4257                 case 5:
4258                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4259                                 return true;
4260                         break;
4261                 case 6:
4262                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4263                                 return true;
4264                         break;
4265                 case 7:
4266                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4267                                 return true;
4268                         break;
4269                 }
4270         }
4271         return false;
4272 }
4273
4274 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4275 {
4276         int i;
4277         const mplane_t *p;
4278         for (i = 0;i < numplanes;i++)
4279         {
4280                 p = planes + i;
4281                 switch(p->signbits)
4282                 {
4283                 default:
4284                 case 0:
4285                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4286                                 return true;
4287                         break;
4288                 case 1:
4289                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4290                                 return true;
4291                         break;
4292                 case 2:
4293                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4294                                 return true;
4295                         break;
4296                 case 3:
4297                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4298                                 return true;
4299                         break;
4300                 case 4:
4301                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4302                                 return true;
4303                         break;
4304                 case 5:
4305                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4306                                 return true;
4307                         break;
4308                 case 6:
4309                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4310                                 return true;
4311                         break;
4312                 case 7:
4313                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4314                                 return true;
4315                         break;
4316                 }
4317         }
4318         return false;
4319 }
4320
4321 //==================================================================================
4322
4323 // LordHavoc: this stores temporary data used within the same frame
4324
4325 typedef struct r_framedata_mem_s
4326 {
4327         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4328         size_t size; // how much usable space
4329         size_t current; // how much space in use
4330         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4331         size_t wantedsize; // how much space was allocated
4332         unsigned char *data; // start of real data (16byte aligned)
4333 }
4334 r_framedata_mem_t;
4335
4336 static r_framedata_mem_t *r_framedata_mem;
4337
4338 void R_FrameData_Reset(void)
4339 {
4340         while (r_framedata_mem)
4341         {
4342                 r_framedata_mem_t *next = r_framedata_mem->purge;
4343                 Mem_Free(r_framedata_mem);
4344                 r_framedata_mem = next;
4345         }
4346 }
4347
4348 void R_FrameData_Resize(void)
4349 {
4350         size_t wantedsize;
4351         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4352         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4353         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4354         {
4355                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4356                 newmem->wantedsize = wantedsize;
4357                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4358                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4359                 newmem->current = 0;
4360                 newmem->mark = 0;
4361                 newmem->purge = r_framedata_mem;
4362                 r_framedata_mem = newmem;
4363         }
4364 }
4365
4366 void R_FrameData_NewFrame(void)
4367 {
4368         R_FrameData_Resize();
4369         if (!r_framedata_mem)
4370                 return;
4371         // if we ran out of space on the last frame, free the old memory now
4372         while (r_framedata_mem->purge)
4373         {
4374                 // repeatedly remove the second item in the list, leaving only head
4375                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4376                 Mem_Free(r_framedata_mem->purge);
4377                 r_framedata_mem->purge = next;
4378         }
4379         // reset the current mem pointer
4380         r_framedata_mem->current = 0;
4381         r_framedata_mem->mark = 0;
4382 }
4383
4384 void *R_FrameData_Alloc(size_t size)
4385 {
4386         void *data;
4387
4388         // align to 16 byte boundary - the data pointer is already aligned, so we
4389         // only need to ensure the size of every allocation is also aligned
4390         size = (size + 15) & ~15;
4391
4392         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4393         {
4394                 // emergency - we ran out of space, allocate more memory
4395                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4396                 R_FrameData_Resize();
4397         }
4398
4399         data = r_framedata_mem->data + r_framedata_mem->current;
4400         r_framedata_mem->current += size;
4401
4402         // count the usage for stats
4403         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4404         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4405
4406         return (void *)data;
4407 }
4408
4409 void *R_FrameData_Store(size_t size, void *data)
4410 {
4411         void *d = R_FrameData_Alloc(size);
4412         if (d && data)
4413                 memcpy(d, data, size);
4414         return d;
4415 }
4416
4417 void R_FrameData_SetMark(void)
4418 {
4419         if (!r_framedata_mem)
4420                 return;
4421         r_framedata_mem->mark = r_framedata_mem->current;
4422 }
4423
4424 void R_FrameData_ReturnToMark(void)
4425 {
4426         if (!r_framedata_mem)
4427                 return;
4428         r_framedata_mem->current = r_framedata_mem->mark;
4429 }
4430
4431 //==================================================================================
4432
4433 // LordHavoc: animcache originally written by Echon, rewritten since then
4434
4435 /**
4436  * Animation cache prevents re-generating mesh data for an animated model
4437  * multiple times in one frame for lighting, shadowing, reflections, etc.
4438  */
4439
4440 void R_AnimCache_Free(void)
4441 {
4442 }
4443
4444 void R_AnimCache_ClearCache(void)
4445 {
4446         int i;
4447         entity_render_t *ent;
4448
4449         for (i = 0;i < r_refdef.scene.numentities;i++)
4450         {
4451                 ent = r_refdef.scene.entities[i];
4452                 ent->animcache_vertex3f = NULL;
4453                 ent->animcache_normal3f = NULL;
4454                 ent->animcache_svector3f = NULL;
4455                 ent->animcache_tvector3f = NULL;
4456                 ent->animcache_vertexmesh = NULL;
4457                 ent->animcache_vertex3fbuffer = NULL;
4458                 ent->animcache_vertexmeshbuffer = NULL;
4459         }
4460 }
4461
4462 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4463 {
4464         int i;
4465
4466         // check if we need the meshbuffers
4467         if (!vid.useinterleavedarrays)
4468                 return;
4469
4470         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4471                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4472         // TODO: upload vertex3f buffer?
4473         if (ent->animcache_vertexmesh)
4474         {
4475                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4476                 for (i = 0;i < numvertices;i++)
4477                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4478                 if (ent->animcache_svector3f)
4479                         for (i = 0;i < numvertices;i++)
4480                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4481                 if (ent->animcache_tvector3f)
4482                         for (i = 0;i < numvertices;i++)
4483                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4484                 if (ent->animcache_normal3f)
4485                         for (i = 0;i < numvertices;i++)
4486                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4487                 // TODO: upload vertexmeshbuffer?
4488         }
4489 }
4490
4491 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4492 {
4493         dp_model_t *model = ent->model;
4494         int numvertices;
4495         // see if it's already cached this frame
4496         if (ent->animcache_vertex3f)
4497         {
4498                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4499                 if (wantnormals || wanttangents)
4500                 {
4501                         if (ent->animcache_normal3f)
4502                                 wantnormals = false;
4503                         if (ent->animcache_svector3f)
4504                                 wanttangents = false;
4505                         if (wantnormals || wanttangents)
4506                         {
4507                                 numvertices = model->surfmesh.num_vertices;
4508                                 if (wantnormals)
4509                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4510                                 if (wanttangents)
4511                                 {
4512                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4513                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4514                                 }
4515                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4516                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4517                         }
4518                 }
4519         }
4520         else
4521         {
4522                 // see if this ent is worth caching
4523                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4524                         return false;
4525                 // get some memory for this entity and generate mesh data
4526                 numvertices = model->surfmesh.num_vertices;
4527                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4528                 if (wantnormals)
4529                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4530                 if (wanttangents)
4531                 {
4532                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4533                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4534                 }
4535                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4536                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4537         }
4538         return true;
4539 }
4540
4541 void R_AnimCache_CacheVisibleEntities(void)
4542 {
4543         int i;
4544         qboolean wantnormals = true;
4545         qboolean wanttangents = !r_showsurfaces.integer;
4546
4547         switch(vid.renderpath)
4548         {
4549         case RENDERPATH_GL20:
4550         case RENDERPATH_D3D9:
4551         case RENDERPATH_D3D10:
4552         case RENDERPATH_D3D11:
4553         case RENDERPATH_GLES2:
4554                 break;
4555         case RENDERPATH_GL13:
4556         case RENDERPATH_GL11:
4557                 wanttangents = false;
4558                 break;
4559         case RENDERPATH_SOFT:
4560                 break;
4561         }
4562
4563         if (r_shownormals.integer)
4564                 wanttangents = wantnormals = true;
4565
4566         // TODO: thread this
4567         // NOTE: R_PrepareRTLights() also caches entities
4568
4569         for (i = 0;i < r_refdef.scene.numentities;i++)
4570                 if (r_refdef.viewcache.entityvisible[i])
4571                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4572 }
4573
4574 //==================================================================================
4575
4576 static void R_View_UpdateEntityLighting (void)
4577 {
4578         int i;
4579         entity_render_t *ent;
4580         vec3_t tempdiffusenormal, avg;
4581         vec_t f, fa, fd, fdd;
4582         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4583
4584         for (i = 0;i < r_refdef.scene.numentities;i++)
4585         {
4586                 ent = r_refdef.scene.entities[i];
4587
4588                 // skip unseen models
4589                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4590                         continue;
4591
4592                 // skip bsp models
4593                 if (ent->model && ent->model->brush.num_leafs)
4594                 {
4595                         // TODO: use modellight for r_ambient settings on world?
4596                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4597                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4598                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4599                         continue;
4600                 }
4601
4602                 // fetch the lighting from the worldmodel data
4603                 VectorClear(ent->modellight_ambient);
4604                 VectorClear(ent->modellight_diffuse);
4605                 VectorClear(tempdiffusenormal);
4606                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4607                 {
4608                         vec3_t org;
4609                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4610
4611                         // complete lightning for lit sprites
4612                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4613                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4614                         {
4615                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4616                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4617                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4618                         }
4619                         else
4620                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4621
4622                         if(ent->flags & RENDER_EQUALIZE)
4623                         {
4624                                 // first fix up ambient lighting...
4625                                 if(r_equalize_entities_minambient.value > 0)
4626                                 {
4627                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4628                                         if(fd > 0)
4629                                         {
4630                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4631                                                 if(fa < r_equalize_entities_minambient.value * fd)
4632                                                 {
4633                                                         // solve:
4634                                                         //   fa'/fd' = minambient
4635                                                         //   fa'+0.25*fd' = fa+0.25*fd
4636                                                         //   ...
4637                                                         //   fa' = fd' * minambient
4638                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4639                                                         //   ...
4640                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4641                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4642                                                         //   ...
4643                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4644                                                         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
4645                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4646                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4647                                                 }
4648                                         }
4649                                 }
4650
4651                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4652                                 {
4653                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4654                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4655                                         f = fa + 0.25 * fd;
4656                                         if(f > 0)
4657                                         {
4658                                                 // adjust brightness and saturation to target
4659                                                 avg[0] = avg[1] = avg[2] = fa / f;
4660                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4661                                                 avg[0] = avg[1] = avg[2] = fd / f;
4662                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4663                                         }
4664                                 }
4665                         }
4666                 }
4667                 else // highly rare
4668                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4669
4670                 // move the light direction into modelspace coordinates for lighting code
4671                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4672                 if(VectorLength2(ent->modellight_lightdir) == 0)
4673                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4674                 VectorNormalize(ent->modellight_lightdir);
4675         }
4676 }
4677
4678 #define MAX_LINEOFSIGHTTRACES 64
4679
4680 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4681 {
4682         int i;
4683         vec3_t boxmins, boxmaxs;
4684         vec3_t start;
4685         vec3_t end;
4686         dp_model_t *model = r_refdef.scene.worldmodel;
4687
4688         if (!model || !model->brush.TraceLineOfSight)
4689                 return true;
4690
4691         // expand the box a little
4692         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4693         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4694         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4695         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4696         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4697         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4698
4699         // return true if eye is inside enlarged box
4700         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4701                 return true;
4702
4703         // try center
4704         VectorCopy(eye, start);
4705         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4706         if (model->brush.TraceLineOfSight(model, start, end))
4707                 return true;
4708
4709         // try various random positions
4710         for (i = 0;i < numsamples;i++)
4711         {
4712                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4713                 if (model->brush.TraceLineOfSight(model, start, end))
4714                         return true;
4715         }
4716
4717         return false;
4718 }
4719
4720
4721 static void R_View_UpdateEntityVisible (void)
4722 {
4723         int i;
4724         int renderimask;
4725         int samples;
4726         entity_render_t *ent;
4727
4728         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4729                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4730                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4731                 :                                                          RENDER_EXTERIORMODEL;
4732         if (!r_drawviewmodel.integer)
4733                 renderimask |= RENDER_VIEWMODEL;
4734         if (!r_drawexteriormodel.integer)
4735                 renderimask |= RENDER_EXTERIORMODEL;
4736         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4737         {
4738                 // worldmodel can check visibility
4739                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4740                 for (i = 0;i < r_refdef.scene.numentities;i++)
4741                 {
4742                         ent = r_refdef.scene.entities[i];
4743                         if (!(ent->flags & renderimask))
4744                         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)))
4745                         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))
4746                                 r_refdef.viewcache.entityvisible[i] = true;
4747                 }
4748                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4749                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4750                 {
4751                         for (i = 0;i < r_refdef.scene.numentities;i++)
4752                         {
4753                                 ent = r_refdef.scene.entities[i];
4754                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4755                                 {
4756                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4757                                         if (samples < 0)
4758                                                 continue; // temp entities do pvs only
4759                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4760                                                 ent->last_trace_visibility = realtime;
4761                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4762                                                 r_refdef.viewcache.entityvisible[i] = 0;
4763                                 }
4764                         }
4765                 }
4766         }
4767         else
4768         {
4769                 // no worldmodel or it can't check visibility
4770                 for (i = 0;i < r_refdef.scene.numentities;i++)
4771                 {
4772                         ent = r_refdef.scene.entities[i];
4773                         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));
4774                 }
4775         }
4776 }
4777
4778 /// only used if skyrendermasked, and normally returns false
4779 int R_DrawBrushModelsSky (void)
4780 {
4781         int i, sky;
4782         entity_render_t *ent;
4783
4784         sky = false;
4785         for (i = 0;i < r_refdef.scene.numentities;i++)
4786         {
4787                 if (!r_refdef.viewcache.entityvisible[i])
4788                         continue;
4789                 ent = r_refdef.scene.entities[i];
4790                 if (!ent->model || !ent->model->DrawSky)
4791                         continue;
4792                 ent->model->DrawSky(ent);
4793                 sky = true;
4794         }
4795         return sky;
4796 }
4797
4798 static void R_DrawNoModel(entity_render_t *ent);
4799 static void R_DrawModels(void)
4800 {
4801         int i;
4802         entity_render_t *ent;
4803
4804         for (i = 0;i < r_refdef.scene.numentities;i++)
4805         {
4806                 if (!r_refdef.viewcache.entityvisible[i])
4807                         continue;
4808                 ent = r_refdef.scene.entities[i];
4809                 r_refdef.stats.entities++;
4810                 if (ent->model && ent->model->Draw != NULL)
4811                         ent->model->Draw(ent);
4812                 else
4813                         R_DrawNoModel(ent);
4814         }
4815 }
4816
4817 static void R_DrawModelsDepth(void)
4818 {
4819         int i;
4820         entity_render_t *ent;
4821
4822         for (i = 0;i < r_refdef.scene.numentities;i++)
4823         {
4824                 if (!r_refdef.viewcache.entityvisible[i])
4825                         continue;
4826                 ent = r_refdef.scene.entities[i];
4827                 if (ent->model && ent->model->DrawDepth != NULL)
4828                         ent->model->DrawDepth(ent);
4829         }
4830 }
4831
4832 static void R_DrawModelsDebug(void)
4833 {
4834         int i;
4835         entity_render_t *ent;
4836
4837         for (i = 0;i < r_refdef.scene.numentities;i++)
4838         {
4839                 if (!r_refdef.viewcache.entityvisible[i])
4840                         continue;
4841                 ent = r_refdef.scene.entities[i];
4842                 if (ent->model && ent->model->DrawDebug != NULL)
4843                         ent->model->DrawDebug(ent);
4844         }
4845 }
4846
4847 static void R_DrawModelsAddWaterPlanes(void)
4848 {
4849         int i;
4850         entity_render_t *ent;
4851
4852         for (i = 0;i < r_refdef.scene.numentities;i++)
4853         {
4854                 if (!r_refdef.viewcache.entityvisible[i])
4855                         continue;
4856                 ent = r_refdef.scene.entities[i];
4857                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4858                         ent->model->DrawAddWaterPlanes(ent);
4859         }
4860 }
4861
4862 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4863 {
4864         if (r_hdr_irisadaptation.integer)
4865         {
4866                 vec3_t ambient;
4867                 vec3_t diffuse;
4868                 vec3_t diffusenormal;
4869                 vec_t brightness;
4870                 vec_t goal;
4871                 vec_t adjust;
4872                 vec_t current;
4873                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4874                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4875                 brightness = max(0.0000001f, brightness);
4876                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4877                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4878                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4879                 current = r_hdr_irisadaptation_value.value;
4880                 if (current < goal)
4881                         current = min(current + adjust, goal);
4882                 else if (current > goal)
4883                         current = max(current - adjust, goal);
4884                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4885                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4886         }
4887         else if (r_hdr_irisadaptation_value.value != 1.0f)
4888                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4889 }
4890
4891 static void R_View_SetFrustum(const int *scissor)
4892 {
4893         int i;
4894         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4895         vec3_t forward, left, up, origin, v;
4896
4897         if(scissor)
4898         {
4899                 // flipped x coordinates (because x points left here)
4900                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4901                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4902
4903                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4904                 switch(vid.renderpath)
4905                 {
4906                         case RENDERPATH_D3D9:
4907                         case RENDERPATH_D3D10:
4908                         case RENDERPATH_D3D11:
4909                         case RENDERPATH_SOFT:
4910                                 // non-flipped y coordinates
4911                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4912                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4913                                 break;
4914                         case RENDERPATH_GL11:
4915                         case RENDERPATH_GL13:
4916                         case RENDERPATH_GL20:
4917                         case RENDERPATH_GLES2:
4918                                 // non-flipped y coordinates
4919                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4920                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4921                                 break;
4922                 }
4923         }
4924
4925         // we can't trust r_refdef.view.forward and friends in reflected scenes
4926         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4927
4928 #if 0
4929         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4930         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4931         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4932         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4933         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4934         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4935         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4936         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4937         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4938         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4939         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4940         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4941 #endif
4942
4943 #if 0
4944         zNear = r_refdef.nearclip;
4945         nudge = 1.0 - 1.0 / (1<<23);
4946         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4947         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4948         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4949         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4950         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4951         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4952         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4953         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4954 #endif
4955
4956
4957
4958 #if 0
4959         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4960         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4961         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4962         r_refdef.view.frustum[0].dist = m[15] - m[12];
4963
4964         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4965         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4966         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4967         r_refdef.view.frustum[1].dist = m[15] + m[12];
4968
4969         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4970         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4971         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4972         r_refdef.view.frustum[2].dist = m[15] - m[13];
4973
4974         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4975         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4976         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4977         r_refdef.view.frustum[3].dist = m[15] + m[13];
4978
4979         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4980         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4981         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4982         r_refdef.view.frustum[4].dist = m[15] - m[14];
4983
4984         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4985         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4986         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4987         r_refdef.view.frustum[5].dist = m[15] + m[14];
4988 #endif
4989
4990         if (r_refdef.view.useperspective)
4991         {
4992                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4993                 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]);
4994                 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]);
4995                 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]);
4996                 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]);
4997
4998                 // then the normals from the corners relative to origin
4999                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5000                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5001                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5002                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5003
5004                 // in a NORMAL view, forward cross left == up
5005                 // in a REFLECTED view, forward cross left == down
5006                 // so our cross products above need to be adjusted for a left handed coordinate system
5007                 CrossProduct(forward, left, v);
5008                 if(DotProduct(v, up) < 0)
5009                 {
5010                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5011                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5012                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5013                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5014                 }
5015
5016                 // Leaving those out was a mistake, those were in the old code, and they
5017                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5018                 // I couldn't reproduce it after adding those normalizations. --blub
5019                 VectorNormalize(r_refdef.view.frustum[0].normal);
5020                 VectorNormalize(r_refdef.view.frustum[1].normal);
5021                 VectorNormalize(r_refdef.view.frustum[2].normal);
5022                 VectorNormalize(r_refdef.view.frustum[3].normal);
5023
5024                 // make the corners absolute
5025                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5026                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5027                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5028                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5029
5030                 // one more normal
5031                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5032
5033                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5034                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5035                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5036                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5037                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5038         }
5039         else
5040         {
5041                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5042                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5043                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5044                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5045                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5046                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5047                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5048                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5049                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5050                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5051         }
5052         r_refdef.view.numfrustumplanes = 5;
5053
5054         if (r_refdef.view.useclipplane)
5055         {
5056                 r_refdef.view.numfrustumplanes = 6;
5057                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5058         }
5059
5060         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5061                 PlaneClassify(r_refdef.view.frustum + i);
5062
5063         // LordHavoc: note to all quake engine coders, Quake had a special case
5064         // for 90 degrees which assumed a square view (wrong), so I removed it,
5065         // Quake2 has it disabled as well.
5066
5067         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5068         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5069         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5070         //PlaneClassify(&frustum[0]);
5071
5072         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5073         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5074         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5075         //PlaneClassify(&frustum[1]);
5076
5077         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5078         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5079         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5080         //PlaneClassify(&frustum[2]);
5081
5082         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5083         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5084         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5085         //PlaneClassify(&frustum[3]);
5086
5087         // nearclip plane
5088         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5089         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5090         //PlaneClassify(&frustum[4]);
5091 }
5092
5093 void R_View_UpdateWithScissor(const int *myscissor)
5094 {
5095         R_Main_ResizeViewCache();
5096         R_View_SetFrustum(myscissor);
5097         R_View_WorldVisibility(r_refdef.view.useclipplane);
5098         R_View_UpdateEntityVisible();
5099         R_View_UpdateEntityLighting();
5100 }
5101
5102 void R_View_Update(void)
5103 {
5104         R_Main_ResizeViewCache();
5105         R_View_SetFrustum(NULL);
5106         R_View_WorldVisibility(r_refdef.view.useclipplane);
5107         R_View_UpdateEntityVisible();
5108         R_View_UpdateEntityLighting();
5109 }
5110
5111 void R_SetupView(qboolean allowwaterclippingplane)
5112 {
5113         const float *customclipplane = NULL;
5114         float plane[4];
5115         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5116         {
5117                 // LordHavoc: couldn't figure out how to make this approach the
5118                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5119                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5120                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5121                         dist = r_refdef.view.clipplane.dist;
5122                 plane[0] = r_refdef.view.clipplane.normal[0];
5123                 plane[1] = r_refdef.view.clipplane.normal[1];
5124                 plane[2] = r_refdef.view.clipplane.normal[2];
5125                 plane[3] = dist;
5126                 customclipplane = plane;
5127         }
5128
5129         if (!r_refdef.view.useperspective)
5130                 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);
5131         else if (vid.stencil && r_useinfinitefarclip.integer)
5132                 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);
5133         else
5134                 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);
5135         R_SetViewport(&r_refdef.view.viewport);
5136 }
5137
5138 void R_EntityMatrix(const matrix4x4_t *matrix)
5139 {
5140         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5141         {
5142                 gl_modelmatrixchanged = false;
5143                 gl_modelmatrix = *matrix;
5144                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5145                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5146                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5147                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5148                 CHECKGLERROR
5149                 switch(vid.renderpath)
5150                 {
5151                 case RENDERPATH_D3D9:
5152 #ifdef SUPPORTD3D
5153                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5154                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5155 #endif
5156                         break;
5157                 case RENDERPATH_D3D10:
5158                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5159                         break;
5160                 case RENDERPATH_D3D11:
5161                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5162                         break;
5163                 case RENDERPATH_GL13:
5164                 case RENDERPATH_GL11:
5165                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5166                         break;
5167                 case RENDERPATH_SOFT:
5168                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5169                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5170                         break;
5171                 case RENDERPATH_GL20:
5172                 case RENDERPATH_GLES2:
5173                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5174                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5175                         break;
5176                 }
5177         }
5178 }
5179
5180 void R_ResetViewRendering2D(void)
5181 {
5182         r_viewport_t viewport;
5183         DrawQ_Finish();
5184
5185         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5186         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);
5187         R_SetViewport(&viewport);
5188         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5189         GL_Color(1, 1, 1, 1);
5190         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5191         GL_BlendFunc(GL_ONE, GL_ZERO);
5192         GL_ScissorTest(false);
5193         GL_DepthMask(false);
5194         GL_DepthRange(0, 1);
5195         GL_DepthTest(false);
5196         GL_DepthFunc(GL_LEQUAL);
5197         R_EntityMatrix(&identitymatrix);
5198         R_Mesh_ResetTextureState();
5199         GL_PolygonOffset(0, 0);
5200         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5201         switch(vid.renderpath)
5202         {
5203         case RENDERPATH_GL11:
5204         case RENDERPATH_GL13:
5205         case RENDERPATH_GL20:
5206         case RENDERPATH_GLES2:
5207                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5208                 break;
5209         case RENDERPATH_D3D9:
5210         case RENDERPATH_D3D10:
5211         case RENDERPATH_D3D11:
5212         case RENDERPATH_SOFT:
5213                 break;
5214         }
5215         GL_CullFace(GL_NONE);
5216 }
5217
5218 void R_ResetViewRendering3D(void)
5219 {
5220         DrawQ_Finish();
5221
5222         R_SetupView(true);
5223         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5224         GL_Color(1, 1, 1, 1);
5225         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5226         GL_BlendFunc(GL_ONE, GL_ZERO);
5227         GL_ScissorTest(true);
5228         GL_DepthMask(true);
5229         GL_DepthRange(0, 1);
5230         GL_DepthTest(true);
5231         GL_DepthFunc(GL_LEQUAL);
5232         R_EntityMatrix(&identitymatrix);
5233         R_Mesh_ResetTextureState();
5234         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5235         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5236         switch(vid.renderpath)
5237         {
5238         case RENDERPATH_GL11:
5239         case RENDERPATH_GL13:
5240         case RENDERPATH_GL20:
5241         case RENDERPATH_GLES2:
5242                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5243                 break;
5244         case RENDERPATH_D3D9:
5245         case RENDERPATH_D3D10:
5246         case RENDERPATH_D3D11:
5247         case RENDERPATH_SOFT:
5248                 break;
5249         }
5250         GL_CullFace(r_refdef.view.cullface_back);
5251 }
5252
5253 /*
5254 ================
5255 R_RenderView_UpdateViewVectors
5256 ================
5257 */
5258 static void R_RenderView_UpdateViewVectors(void)
5259 {
5260         // break apart the view matrix into vectors for various purposes
5261         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5262         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5263         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5264         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5265         // make an inverted copy of the view matrix for tracking sprites
5266         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5267 }
5268
5269 void R_RenderScene(void);
5270 void R_RenderWaterPlanes(void);
5271
5272 static void R_Water_StartFrame(void)
5273 {
5274         int i;
5275         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5276         r_waterstate_waterplane_t *p;
5277
5278         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5279                 return;
5280
5281         switch(vid.renderpath)
5282         {
5283         case RENDERPATH_GL20:
5284         case RENDERPATH_D3D9:
5285         case RENDERPATH_D3D10:
5286         case RENDERPATH_D3D11:
5287         case RENDERPATH_SOFT:
5288         case RENDERPATH_GLES2:
5289                 break;
5290         case RENDERPATH_GL13:
5291         case RENDERPATH_GL11:
5292                 return;
5293         }
5294
5295         // set waterwidth and waterheight to the water resolution that will be
5296         // used (often less than the screen resolution for faster rendering)
5297         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5298         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5299
5300         // calculate desired texture sizes
5301         // can't use water if the card does not support the texture size
5302         if (!r_water.integer || r_showsurfaces.integer)
5303                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5304         else if (vid.support.arb_texture_non_power_of_two)
5305         {
5306                 texturewidth = waterwidth;
5307                 textureheight = waterheight;
5308                 camerawidth = waterwidth;
5309                 cameraheight = waterheight;
5310         }
5311         else
5312         {
5313                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5314                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5315                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5316                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5317         }
5318
5319         // allocate textures as needed
5320         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5321         {
5322                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5323                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5324                 {
5325                         if (p->texture_refraction)
5326                                 R_FreeTexture(p->texture_refraction);
5327                         p->texture_refraction = NULL;
5328                         if (p->texture_reflection)
5329                                 R_FreeTexture(p->texture_reflection);
5330                         p->texture_reflection = NULL;
5331                         if (p->texture_camera)
5332                                 R_FreeTexture(p->texture_camera);
5333                         p->texture_camera = NULL;
5334                 }
5335                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5336                 r_waterstate.texturewidth = texturewidth;
5337                 r_waterstate.textureheight = textureheight;
5338                 r_waterstate.camerawidth = camerawidth;
5339                 r_waterstate.cameraheight = cameraheight;
5340         }
5341
5342         if (r_waterstate.texturewidth)
5343         {
5344                 r_waterstate.enabled = true;
5345
5346                 // when doing a reduced render (HDR) we want to use a smaller area
5347                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5348                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5349
5350                 // set up variables that will be used in shader setup
5351                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5352                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5353                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5354                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5355         }
5356
5357         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5358         r_waterstate.numwaterplanes = 0;
5359 }
5360
5361 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5362 {
5363         int triangleindex, planeindex;
5364         const int *e;
5365         vec3_t vert[3];
5366         vec3_t normal;
5367         vec3_t center;
5368         mplane_t plane;
5369         r_waterstate_waterplane_t *p;
5370         texture_t *t = R_GetCurrentTexture(surface->texture);
5371
5372         // just use the first triangle with a valid normal for any decisions
5373         VectorClear(normal);
5374         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5375         {
5376                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5377                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5378                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5379                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5380                 if (VectorLength2(normal) >= 0.001)
5381                         break;
5382         }
5383
5384         VectorCopy(normal, plane.normal);
5385         VectorNormalize(plane.normal);
5386         plane.dist = DotProduct(vert[0], plane.normal);
5387         PlaneClassify(&plane);
5388         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5389         {
5390                 // skip backfaces (except if nocullface is set)
5391                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5392                         return;
5393                 VectorNegate(plane.normal, plane.normal);
5394                 plane.dist *= -1;
5395                 PlaneClassify(&plane);
5396         }
5397
5398
5399         // find a matching plane if there is one
5400         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5401                 if(p->camera_entity == t->camera_entity)
5402                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5403                                 break;
5404         if (planeindex >= r_waterstate.maxwaterplanes)
5405                 return; // nothing we can do, out of planes
5406
5407         // if this triangle does not fit any known plane rendered this frame, add one
5408         if (planeindex >= r_waterstate.numwaterplanes)
5409         {
5410                 // store the new plane
5411                 r_waterstate.numwaterplanes++;
5412                 p->plane = plane;
5413                 // clear materialflags and pvs
5414                 p->materialflags = 0;
5415                 p->pvsvalid = false;
5416                 p->camera_entity = t->camera_entity;
5417                 VectorCopy(surface->mins, p->mins);
5418                 VectorCopy(surface->maxs, p->maxs);
5419         }
5420         else
5421         {
5422                 // merge mins/maxs
5423                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5424                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5425                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5426                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5427                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5428                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5429         }
5430         // merge this surface's materialflags into the waterplane
5431         p->materialflags |= t->currentmaterialflags;
5432         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5433         {
5434                 // merge this surface's PVS into the waterplane
5435                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5436                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5437                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5438                 {
5439                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5440                         p->pvsvalid = true;
5441                 }
5442         }
5443 }
5444
5445 static void R_Water_ProcessPlanes(void)
5446 {
5447         int myscissor[4];
5448         r_refdef_view_t originalview;
5449         r_refdef_view_t myview;
5450         int planeindex;
5451         r_waterstate_waterplane_t *p;
5452         vec3_t visorigin;
5453
5454         originalview = r_refdef.view;
5455
5456         // make sure enough textures are allocated
5457         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5458         {
5459                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5460                 {
5461                         if (!p->texture_refraction)
5462                                 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);
5463                         if (!p->texture_refraction)
5464                                 goto error;
5465                 }
5466                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5467                 {
5468                         if (!p->texture_camera)
5469                                 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);
5470                         if (!p->texture_camera)
5471                                 goto error;
5472                 }
5473
5474                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5475                 {
5476                         if (!p->texture_reflection)
5477                                 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);
5478                         if (!p->texture_reflection)
5479                                 goto error;
5480                 }
5481         }
5482
5483         // render views
5484         r_refdef.view = originalview;
5485         r_refdef.view.showdebug = false;
5486         r_refdef.view.width = r_waterstate.waterwidth;
5487         r_refdef.view.height = r_waterstate.waterheight;
5488         r_refdef.view.useclipplane = true;
5489         myview = r_refdef.view;
5490         r_waterstate.renderingscene = true;
5491         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5492         {
5493                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5494                 {
5495                         r_refdef.view = myview;
5496                         if(r_water_scissormode.integer)
5497                         {
5498                                 R_SetupView(true);
5499                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5500                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5501                         }
5502
5503                         // render reflected scene and copy into texture
5504                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5505                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5506                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5507                         r_refdef.view.clipplane = p->plane;
5508
5509                         // reverse the cullface settings for this render
5510                         r_refdef.view.cullface_front = GL_FRONT;
5511                         r_refdef.view.cullface_back = GL_BACK;
5512                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5513                         {
5514                                 r_refdef.view.usecustompvs = true;
5515                                 if (p->pvsvalid)
5516                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5517                                 else
5518                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5519                         }
5520
5521                         R_ResetViewRendering3D();
5522                         R_ClearScreen(r_refdef.fogenabled);
5523                         if(r_water_scissormode.integer & 2)
5524                                 R_View_UpdateWithScissor(myscissor);
5525                         else
5526                                 R_View_Update();
5527                         if(r_water_scissormode.integer & 1)
5528                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5529                         R_RenderScene();
5530
5531                         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);
5532                 }
5533
5534                 // render the normal view scene and copy into texture
5535                 // (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)
5536                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5537                 {
5538                         r_refdef.view = myview;
5539                         if(r_water_scissormode.integer)
5540                         {
5541                                 R_SetupView(true);
5542                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5543                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5544                         }
5545
5546                         r_waterstate.renderingrefraction = true;
5547
5548                         r_refdef.view.clipplane = p->plane;
5549                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5550                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5551
5552                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5553                         {
5554                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5555                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5556                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5557                                 R_RenderView_UpdateViewVectors();
5558                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5559                                 {
5560                                         r_refdef.view.usecustompvs = true;
5561                                         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);
5562                                 }
5563                         }
5564
5565                         PlaneClassify(&r_refdef.view.clipplane);
5566
5567                         R_ResetViewRendering3D();
5568                         R_ClearScreen(r_refdef.fogenabled);
5569                         if(r_water_scissormode.integer & 2)
5570                                 R_View_UpdateWithScissor(myscissor);
5571                         else
5572                                 R_View_Update();
5573                         if(r_water_scissormode.integer & 1)
5574                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5575                         R_RenderScene();
5576
5577                         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);
5578                         r_waterstate.renderingrefraction = false;
5579                 }
5580                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5581                 {
5582                         r_refdef.view = myview;
5583
5584                         r_refdef.view.clipplane = p->plane;
5585                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5586                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5587
5588                         r_refdef.view.width = r_waterstate.camerawidth;
5589                         r_refdef.view.height = r_waterstate.cameraheight;
5590                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5591                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5592
5593                         if(p->camera_entity)
5594                         {
5595                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5596                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5597                         }
5598
5599                         // note: all of the view is used for displaying... so
5600                         // there is no use in scissoring
5601
5602                         // reverse the cullface settings for this render
5603                         r_refdef.view.cullface_front = GL_FRONT;
5604                         r_refdef.view.cullface_back = GL_BACK;
5605                         // also reverse the view matrix
5606                         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
5607                         R_RenderView_UpdateViewVectors();
5608                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5609                         {
5610                                 r_refdef.view.usecustompvs = true;
5611                                 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);
5612                         }
5613                         
5614                         // camera needs no clipplane
5615                         r_refdef.view.useclipplane = false;
5616
5617                         PlaneClassify(&r_refdef.view.clipplane);
5618
5619                         R_ResetViewRendering3D();
5620                         R_ClearScreen(r_refdef.fogenabled);
5621                         R_View_Update();
5622                         R_RenderScene();
5623
5624                         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);
5625                         r_waterstate.renderingrefraction = false;
5626                 }
5627
5628         }
5629         r_waterstate.renderingscene = false;
5630         r_refdef.view = originalview;
5631         R_ResetViewRendering3D();
5632         R_ClearScreen(r_refdef.fogenabled);
5633         R_View_Update();
5634         return;
5635 error:
5636         r_refdef.view = originalview;
5637         r_waterstate.renderingscene = false;
5638         Cvar_SetValueQuick(&r_water, 0);
5639         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5640         return;
5641 }
5642
5643 void R_Bloom_StartFrame(void)
5644 {
5645         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5646
5647         switch(vid.renderpath)
5648         {
5649         case RENDERPATH_GL20:
5650         case RENDERPATH_D3D9:
5651         case RENDERPATH_D3D10:
5652         case RENDERPATH_D3D11:
5653         case RENDERPATH_SOFT:
5654         case RENDERPATH_GLES2:
5655                 break;
5656         case RENDERPATH_GL13:
5657         case RENDERPATH_GL11:
5658                 return;
5659         }
5660
5661         // set bloomwidth and bloomheight to the bloom resolution that will be
5662         // used (often less than the screen resolution for faster rendering)
5663         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5664         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5665         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5666         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5667         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5668
5669         // calculate desired texture sizes
5670         if (vid.support.arb_texture_non_power_of_two)
5671         {
5672                 screentexturewidth = r_refdef.view.width;
5673                 screentextureheight = r_refdef.view.height;
5674                 bloomtexturewidth = r_bloomstate.bloomwidth;
5675                 bloomtextureheight = r_bloomstate.bloomheight;
5676         }
5677         else
5678         {
5679                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5680                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5681                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5682                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5683         }
5684
5685         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))
5686         {
5687                 Cvar_SetValueQuick(&r_hdr, 0);
5688                 Cvar_SetValueQuick(&r_bloom, 0);
5689                 Cvar_SetValueQuick(&r_motionblur, 0);
5690                 Cvar_SetValueQuick(&r_damageblur, 0);
5691         }
5692
5693         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)))
5694                 screentexturewidth = screentextureheight = 0;
5695         if (!r_hdr.integer && !r_bloom.integer)
5696                 bloomtexturewidth = bloomtextureheight = 0;
5697
5698         // allocate textures as needed
5699         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5700         {
5701                 if (r_bloomstate.texture_screen)
5702                         R_FreeTexture(r_bloomstate.texture_screen);
5703                 r_bloomstate.texture_screen = NULL;
5704                 r_bloomstate.screentexturewidth = screentexturewidth;
5705                 r_bloomstate.screentextureheight = screentextureheight;
5706                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5707                         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);
5708         }
5709         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5710         {
5711                 if (r_bloomstate.texture_bloom)
5712                         R_FreeTexture(r_bloomstate.texture_bloom);
5713                 r_bloomstate.texture_bloom = NULL;
5714                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5715                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5716                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5717                         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);
5718         }
5719
5720         // when doing a reduced render (HDR) we want to use a smaller area
5721         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5722         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5723         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5724         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5725         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5726
5727         // set up a texcoord array for the full resolution screen image
5728         // (we have to keep this around to copy back during final render)
5729         r_bloomstate.screentexcoord2f[0] = 0;
5730         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5731         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5732         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5733         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5734         r_bloomstate.screentexcoord2f[5] = 0;
5735         r_bloomstate.screentexcoord2f[6] = 0;
5736         r_bloomstate.screentexcoord2f[7] = 0;
5737
5738         // set up a texcoord array for the reduced resolution bloom image
5739         // (which will be additive blended over the screen image)
5740         r_bloomstate.bloomtexcoord2f[0] = 0;
5741         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5742         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5743         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5744         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5745         r_bloomstate.bloomtexcoord2f[5] = 0;
5746         r_bloomstate.bloomtexcoord2f[6] = 0;
5747         r_bloomstate.bloomtexcoord2f[7] = 0;
5748
5749         switch(vid.renderpath)
5750         {
5751         case RENDERPATH_GL11:
5752         case RENDERPATH_GL13:
5753         case RENDERPATH_GL20:
5754         case RENDERPATH_SOFT:
5755         case RENDERPATH_GLES2:
5756                 break;
5757         case RENDERPATH_D3D9:
5758         case RENDERPATH_D3D10:
5759         case RENDERPATH_D3D11:
5760                 {
5761                         int i;
5762                         for (i = 0;i < 4;i++)
5763                         {
5764                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5765                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5766                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5767                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5768                         }
5769                 }
5770                 break;
5771         }
5772
5773         if (r_hdr.integer || r_bloom.integer)
5774         {
5775                 r_bloomstate.enabled = true;
5776                 r_bloomstate.hdr = r_hdr.integer != 0;
5777         }
5778
5779         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);
5780 }
5781
5782 void R_Bloom_CopyBloomTexture(float colorscale)
5783 {
5784         r_refdef.stats.bloom++;
5785
5786         // scale down screen texture to the bloom texture size
5787         CHECKGLERROR
5788         R_SetViewport(&r_bloomstate.viewport);
5789         GL_BlendFunc(GL_ONE, GL_ZERO);
5790         GL_Color(colorscale, colorscale, colorscale, 1);
5791         // 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...
5792         switch(vid.renderpath)
5793         {
5794         case RENDERPATH_GL11:
5795         case RENDERPATH_GL13:
5796         case RENDERPATH_GL20:
5797         case RENDERPATH_SOFT:
5798         case RENDERPATH_GLES2:
5799                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5800                 break;
5801         case RENDERPATH_D3D9:
5802         case RENDERPATH_D3D10:
5803         case RENDERPATH_D3D11:
5804                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5805                 break;
5806         }
5807         // TODO: do boxfilter scale-down in shader?
5808         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5809         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5810         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5811
5812         // we now have a bloom image in the framebuffer
5813         // copy it into the bloom image texture for later processing
5814         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);
5815         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5816 }
5817
5818 void R_Bloom_CopyHDRTexture(void)
5819 {
5820         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);
5821         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5822 }
5823
5824 void R_Bloom_MakeTexture(void)
5825 {
5826         int x, range, dir;
5827         float xoffset, yoffset, r, brighten;
5828
5829         r_refdef.stats.bloom++;
5830
5831         R_ResetViewRendering2D();
5832
5833         // we have a bloom image in the framebuffer
5834         CHECKGLERROR
5835         R_SetViewport(&r_bloomstate.viewport);
5836
5837         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5838         {
5839                 x *= 2;
5840                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5841                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5842                 GL_Color(r,r,r,1);
5843                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5844                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5845                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5846                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5847
5848                 // copy the vertically blurred bloom view to a texture
5849                 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);
5850                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5851         }
5852
5853         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5854         brighten = r_bloom_brighten.value;
5855         if (r_hdr.integer)
5856                 brighten *= r_hdr_range.value;
5857         brighten = sqrt(brighten);
5858         if(range >= 1)
5859                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5860         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5861
5862         for (dir = 0;dir < 2;dir++)
5863         {
5864                 // blend on at multiple vertical offsets to achieve a vertical blur
5865                 // TODO: do offset blends using GLSL
5866                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5867                 GL_BlendFunc(GL_ONE, GL_ZERO);
5868                 for (x = -range;x <= range;x++)
5869                 {
5870                         if (!dir){xoffset = 0;yoffset = x;}
5871                         else {xoffset = x;yoffset = 0;}
5872                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5873                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5874                         // compute a texcoord array with the specified x and y offset
5875                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5876                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5877                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5878                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5879                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5880                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5881                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5882                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5883                         // this r value looks like a 'dot' particle, fading sharply to
5884                         // black at the edges
5885                         // (probably not realistic but looks good enough)
5886                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5887                         //r = brighten/(range*2+1);
5888                         r = brighten / (range * 2 + 1);
5889                         if(range >= 1)
5890                                 r *= (1 - x*x/(float)(range*range));
5891                         GL_Color(r, r, r, 1);
5892                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5893                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5894                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5895                         GL_BlendFunc(GL_ONE, GL_ONE);
5896                 }
5897
5898                 // copy the vertically blurred bloom view to a texture
5899                 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);
5900                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5901         }
5902 }
5903
5904 void R_HDR_RenderBloomTexture(void)
5905 {
5906         int oldwidth, oldheight;
5907         float oldcolorscale;
5908         qboolean oldwaterstate;
5909
5910         oldwaterstate = r_waterstate.enabled;
5911         oldcolorscale = r_refdef.view.colorscale;
5912         oldwidth = r_refdef.view.width;
5913         oldheight = r_refdef.view.height;
5914         r_refdef.view.width = r_bloomstate.bloomwidth;
5915         r_refdef.view.height = r_bloomstate.bloomheight;
5916
5917         if(r_hdr.integer < 2)
5918                 r_waterstate.enabled = false;
5919
5920         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5921         // TODO: add exposure compensation features
5922         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5923
5924         r_refdef.view.showdebug = false;
5925         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5926
5927         R_ResetViewRendering3D();
5928
5929         R_ClearScreen(r_refdef.fogenabled);
5930         if (r_timereport_active)
5931                 R_TimeReport("HDRclear");
5932
5933         R_View_Update();
5934         if (r_timereport_active)
5935                 R_TimeReport("visibility");
5936
5937         // only do secondary renders with HDR if r_hdr is 2 or higher
5938         r_waterstate.numwaterplanes = 0;
5939         if (r_waterstate.enabled)
5940                 R_RenderWaterPlanes();
5941
5942         r_refdef.view.showdebug = true;
5943         R_RenderScene();
5944         r_waterstate.numwaterplanes = 0;
5945
5946         R_ResetViewRendering2D();
5947
5948         R_Bloom_CopyHDRTexture();
5949         R_Bloom_MakeTexture();
5950
5951         // restore the view settings
5952         r_waterstate.enabled = oldwaterstate;
5953         r_refdef.view.width = oldwidth;
5954         r_refdef.view.height = oldheight;
5955         r_refdef.view.colorscale = oldcolorscale;
5956
5957         R_ResetViewRendering3D();
5958
5959         R_ClearScreen(r_refdef.fogenabled);
5960         if (r_timereport_active)
5961                 R_TimeReport("viewclear");
5962 }
5963
5964 static void R_BlendView(void)
5965 {
5966         unsigned int permutation;
5967         float uservecs[4][4];
5968
5969         switch (vid.renderpath)
5970         {
5971         case RENDERPATH_GL20:
5972         case RENDERPATH_D3D9:
5973         case RENDERPATH_D3D10:
5974         case RENDERPATH_D3D11:
5975         case RENDERPATH_SOFT:
5976         case RENDERPATH_GLES2:
5977                 permutation =
5978                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5979                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5980                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5981                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5982                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5983
5984                 if (r_bloomstate.texture_screen)
5985                 {
5986                         // make sure the buffer is available
5987                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5988
5989                         R_ResetViewRendering2D();
5990
5991                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5992                         {
5993                                 // declare variables
5994                                 float speed;
5995                                 static float avgspeed;
5996
5997                                 speed = VectorLength(cl.movement_velocity);
5998
5999                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6000                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6001
6002                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6003                                 speed = bound(0, speed, 1);
6004                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6005
6006                                 // calculate values into a standard alpha
6007                                 cl.motionbluralpha = 1 - exp(-
6008                                                 (
6009                                                  (r_motionblur.value * speed / 80)
6010                                                  +
6011                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6012                                                 )
6013                                                 /
6014                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6015                                            );
6016
6017                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6018                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6019                                 // apply the blur
6020                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6021                                 {
6022                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6023                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6024                                         switch(vid.renderpath)
6025                                         {
6026                                         case RENDERPATH_GL11:
6027                                         case RENDERPATH_GL13:
6028                                         case RENDERPATH_GL20:
6029                                         case RENDERPATH_SOFT:
6030                                         case RENDERPATH_GLES2:
6031                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6032                                                 break;
6033                                         case RENDERPATH_D3D9:
6034                                         case RENDERPATH_D3D10:
6035                                         case RENDERPATH_D3D11:
6036                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6037                                                 break;
6038                                         }
6039                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6040                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6041                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6042                                 }
6043                         }
6044
6045                         // copy view into the screen texture
6046                         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);
6047                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6048                 }
6049                 else if (!r_bloomstate.texture_bloom)
6050                 {
6051                         // we may still have to do view tint...
6052                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6053                         {
6054                                 // apply a color tint to the whole view
6055                                 R_ResetViewRendering2D();
6056                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6057                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6058                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6059                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6060                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6061                         }
6062                         break; // no screen processing, no bloom, skip it
6063                 }
6064
6065                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6066                 {
6067                         // render simple bloom effect
6068                         // copy the screen and shrink it and darken it for the bloom process
6069                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6070                         // make the bloom texture
6071                         R_Bloom_MakeTexture();
6072                 }
6073
6074 #if _MSC_VER >= 1400
6075 #define sscanf sscanf_s
6076 #endif
6077                 memset(uservecs, 0, sizeof(uservecs));
6078                 if (r_glsl_postprocess_uservec1_enable.integer)
6079                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6080                 if (r_glsl_postprocess_uservec2_enable.integer)
6081                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6082                 if (r_glsl_postprocess_uservec3_enable.integer)
6083                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6084                 if (r_glsl_postprocess_uservec4_enable.integer)
6085                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6086
6087                 R_ResetViewRendering2D();
6088                 GL_Color(1, 1, 1, 1);
6089                 GL_BlendFunc(GL_ONE, GL_ZERO);
6090
6091                 switch(vid.renderpath)
6092                 {
6093                 case RENDERPATH_GL20:
6094                 case RENDERPATH_GLES2:
6095                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6096                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6097                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6098                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6099                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6100                         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]);
6101                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6102                         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]);
6103                         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]);
6104                         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]);
6105                         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]);
6106                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6107                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6108                         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);
6109                         break;
6110                 case RENDERPATH_D3D9:
6111 #ifdef SUPPORTD3D
6112                         // 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...
6113                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6114                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6115                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6116                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6117                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6118                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6119                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6120                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6121                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6122                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6123                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6124                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6125                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6126                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6127 #endif
6128                         break;
6129                 case RENDERPATH_D3D10:
6130                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6131                         break;
6132                 case RENDERPATH_D3D11:
6133                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6134                         break;
6135                 case RENDERPATH_SOFT:
6136                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6137                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6138                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6139                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6140                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6141                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6142                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6143                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6144                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6145                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6146                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6147                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6148                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6149                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6150                         break;
6151                 default:
6152                         break;
6153                 }
6154                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6155                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6156                 break;
6157         case RENDERPATH_GL13:
6158         case RENDERPATH_GL11:
6159                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6160                 {
6161                         // apply a color tint to the whole view
6162                         R_ResetViewRendering2D();
6163                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6164                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6165                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6166                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6167                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6168                 }
6169                 break;
6170         }
6171 }
6172
6173 matrix4x4_t r_waterscrollmatrix;
6174
6175 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6176 {
6177         if (r_refdef.fog_density)
6178         {
6179                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6180                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6181                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6182
6183                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6184                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6185                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6186                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6187
6188                 {
6189                         vec3_t fogvec;
6190                         VectorCopy(r_refdef.fogcolor, fogvec);
6191                         //   color.rgb *= ContrastBoost * SceneBrightness;
6192                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6193                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6194                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6195                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6196                 }
6197         }
6198 }
6199
6200 void R_UpdateVariables(void)
6201 {
6202         R_Textures_Frame();
6203
6204         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6205
6206         r_refdef.farclip = r_farclip_base.value;
6207         if (r_refdef.scene.worldmodel)
6208                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6209         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6210
6211         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6212                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6213         r_refdef.polygonfactor = 0;
6214         r_refdef.polygonoffset = 0;
6215         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6216         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6217
6218         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6219         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6220         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6221         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6222         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6223         if (FAKELIGHT_ENABLED)
6224         {
6225                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6226         }
6227         if (r_showsurfaces.integer)
6228         {
6229                 r_refdef.scene.rtworld = false;
6230                 r_refdef.scene.rtworldshadows = false;
6231                 r_refdef.scene.rtdlight = false;
6232                 r_refdef.scene.rtdlightshadows = false;
6233                 r_refdef.lightmapintensity = 0;
6234         }
6235
6236         if (gamemode == GAME_NEHAHRA)
6237         {
6238                 if (gl_fogenable.integer)
6239                 {
6240                         r_refdef.oldgl_fogenable = true;
6241                         r_refdef.fog_density = gl_fogdensity.value;
6242                         r_refdef.fog_red = gl_fogred.value;
6243                         r_refdef.fog_green = gl_foggreen.value;
6244                         r_refdef.fog_blue = gl_fogblue.value;
6245                         r_refdef.fog_alpha = 1;
6246                         r_refdef.fog_start = 0;
6247                         r_refdef.fog_end = gl_skyclip.value;
6248                         r_refdef.fog_height = 1<<30;
6249                         r_refdef.fog_fadedepth = 128;
6250                 }
6251                 else if (r_refdef.oldgl_fogenable)
6252                 {
6253                         r_refdef.oldgl_fogenable = false;
6254                         r_refdef.fog_density = 0;
6255                         r_refdef.fog_red = 0;
6256                         r_refdef.fog_green = 0;
6257                         r_refdef.fog_blue = 0;
6258                         r_refdef.fog_alpha = 0;
6259                         r_refdef.fog_start = 0;
6260                         r_refdef.fog_end = 0;
6261                         r_refdef.fog_height = 1<<30;
6262                         r_refdef.fog_fadedepth = 128;
6263                 }
6264         }
6265
6266         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6267         r_refdef.fog_start = max(0, r_refdef.fog_start);
6268         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6269
6270         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6271
6272         if (r_refdef.fog_density && r_drawfog.integer)
6273         {
6274                 r_refdef.fogenabled = true;
6275                 // this is the point where the fog reaches 0.9986 alpha, which we
6276                 // consider a good enough cutoff point for the texture
6277                 // (0.9986 * 256 == 255.6)
6278                 if (r_fog_exp2.integer)
6279                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6280                 else
6281                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6282                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6283                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6284                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6285                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6286                         R_BuildFogHeightTexture();
6287                 // fog color was already set
6288                 // update the fog texture
6289                 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)
6290                         R_BuildFogTexture();
6291                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6292                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6293         }
6294         else
6295                 r_refdef.fogenabled = false;
6296
6297         switch(vid.renderpath)
6298         {
6299         case RENDERPATH_GL20:
6300         case RENDERPATH_D3D9:
6301         case RENDERPATH_D3D10:
6302         case RENDERPATH_D3D11:
6303         case RENDERPATH_SOFT:
6304         case RENDERPATH_GLES2:
6305                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6306                 {
6307                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6308                         {
6309                                 // build GLSL gamma texture
6310 #define RAMPWIDTH 256
6311                                 unsigned short ramp[RAMPWIDTH * 3];
6312                                 unsigned char rampbgr[RAMPWIDTH][4];
6313                                 int i;
6314
6315                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6316
6317                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6318                                 for(i = 0; i < RAMPWIDTH; ++i)
6319                                 {
6320                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6321                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6322                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6323                                         rampbgr[i][3] = 0;
6324                                 }
6325                                 if (r_texture_gammaramps)
6326                                 {
6327                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6328                                 }
6329                                 else
6330                                 {
6331                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6332                                 }
6333                         }
6334                 }
6335                 else
6336                 {
6337                         // remove GLSL gamma texture
6338                 }
6339                 break;
6340         case RENDERPATH_GL13:
6341         case RENDERPATH_GL11:
6342                 break;
6343         }
6344 }
6345
6346 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6347 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6348 /*
6349 ================
6350 R_SelectScene
6351 ================
6352 */
6353 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6354         if( scenetype != r_currentscenetype ) {
6355                 // store the old scenetype
6356                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6357                 r_currentscenetype = scenetype;
6358                 // move in the new scene
6359                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6360         }
6361 }
6362
6363 /*
6364 ================
6365 R_GetScenePointer
6366 ================
6367 */
6368 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6369 {
6370         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6371         if( scenetype == r_currentscenetype ) {
6372                 return &r_refdef.scene;
6373         } else {
6374                 return &r_scenes_store[ scenetype ];
6375         }
6376 }
6377
6378 /*
6379 ================
6380 R_RenderView
6381 ================
6382 */
6383 int dpsoftrast_test;
6384 void R_RenderView(void)
6385 {
6386         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6387
6388         dpsoftrast_test = r_test.integer;
6389
6390         if (r_timereport_active)
6391                 R_TimeReport("start");
6392         r_textureframe++; // used only by R_GetCurrentTexture
6393         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6394
6395         if(R_CompileShader_CheckStaticParms())
6396                 R_GLSL_Restart_f();
6397
6398         if (!r_drawentities.integer)
6399                 r_refdef.scene.numentities = 0;
6400
6401         R_AnimCache_ClearCache();
6402         R_FrameData_NewFrame();
6403
6404         /* adjust for stereo display */
6405         if(R_Stereo_Active())
6406         {
6407                 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);
6408                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6409         }
6410
6411         if (r_refdef.view.isoverlay)
6412         {
6413                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6414                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6415                 R_TimeReport("depthclear");
6416
6417                 r_refdef.view.showdebug = false;
6418
6419                 r_waterstate.enabled = false;
6420                 r_waterstate.numwaterplanes = 0;
6421
6422                 R_RenderScene();
6423
6424                 r_refdef.view.matrix = originalmatrix;
6425
6426                 CHECKGLERROR
6427                 return;
6428         }
6429
6430         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6431         {
6432                 r_refdef.view.matrix = originalmatrix;
6433                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6434         }
6435
6436         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6437
6438         R_RenderView_UpdateViewVectors();
6439
6440         R_Shadow_UpdateWorldLightSelection();
6441
6442         R_Bloom_StartFrame();
6443         R_Water_StartFrame();
6444
6445         CHECKGLERROR
6446         if (r_timereport_active)
6447                 R_TimeReport("viewsetup");
6448
6449         R_ResetViewRendering3D();
6450
6451         if (r_refdef.view.clear || r_refdef.fogenabled)
6452         {
6453                 R_ClearScreen(r_refdef.fogenabled);
6454                 if (r_timereport_active)
6455                         R_TimeReport("viewclear");
6456         }
6457         r_refdef.view.clear = true;
6458
6459         // this produces a bloom texture to be used in R_BlendView() later
6460         if (r_hdr.integer && r_bloomstate.bloomwidth)
6461         {
6462                 R_HDR_RenderBloomTexture();
6463                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6464                 r_textureframe++; // used only by R_GetCurrentTexture
6465         }
6466
6467         r_refdef.view.showdebug = true;
6468
6469         R_View_Update();
6470         if (r_timereport_active)
6471                 R_TimeReport("visibility");
6472
6473         r_waterstate.numwaterplanes = 0;
6474         if (r_waterstate.enabled)
6475                 R_RenderWaterPlanes();
6476
6477         R_RenderScene();
6478         r_waterstate.numwaterplanes = 0;
6479
6480         R_BlendView();
6481         if (r_timereport_active)
6482                 R_TimeReport("blendview");
6483
6484         GL_Scissor(0, 0, vid.width, vid.height);
6485         GL_ScissorTest(false);
6486
6487         r_refdef.view.matrix = originalmatrix;
6488
6489         CHECKGLERROR
6490 }
6491
6492 void R_RenderWaterPlanes(void)
6493 {
6494         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6495         {
6496                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6497                 if (r_timereport_active)
6498                         R_TimeReport("waterworld");
6499         }
6500
6501         // don't let sound skip if going slow
6502         if (r_refdef.scene.extraupdate)
6503                 S_ExtraUpdate ();
6504
6505         R_DrawModelsAddWaterPlanes();
6506         if (r_timereport_active)
6507                 R_TimeReport("watermodels");
6508
6509         if (r_waterstate.numwaterplanes)
6510         {
6511                 R_Water_ProcessPlanes();
6512                 if (r_timereport_active)
6513                         R_TimeReport("waterscenes");
6514         }
6515 }
6516
6517 extern void R_DrawLightningBeams (void);
6518 extern void VM_CL_AddPolygonsToMeshQueue (void);
6519 extern void R_DrawPortals (void);
6520 extern cvar_t cl_locs_show;
6521 static void R_DrawLocs(void);
6522 static void R_DrawEntityBBoxes(void);
6523 static void R_DrawModelDecals(void);
6524 extern void R_DrawModelShadows(void);
6525 extern void R_DrawModelShadowMaps(void);
6526 extern cvar_t cl_decals_newsystem;
6527 extern qboolean r_shadow_usingdeferredprepass;
6528 void R_RenderScene(void)
6529 {
6530         qboolean shadowmapping = false;
6531
6532         if (r_timereport_active)
6533                 R_TimeReport("beginscene");
6534
6535         r_refdef.stats.renders++;
6536
6537         R_UpdateFogColor();
6538
6539         // don't let sound skip if going slow
6540         if (r_refdef.scene.extraupdate)
6541                 S_ExtraUpdate ();
6542
6543         R_MeshQueue_BeginScene();
6544
6545         R_SkyStartFrame();
6546
6547         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);
6548
6549         if (r_timereport_active)
6550                 R_TimeReport("skystartframe");
6551
6552         if (cl.csqc_vidvars.drawworld)
6553         {
6554                 // don't let sound skip if going slow
6555                 if (r_refdef.scene.extraupdate)
6556                         S_ExtraUpdate ();
6557
6558                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6559                 {
6560                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6561                         if (r_timereport_active)
6562                                 R_TimeReport("worldsky");
6563                 }
6564
6565                 if (R_DrawBrushModelsSky() && r_timereport_active)
6566                         R_TimeReport("bmodelsky");
6567
6568                 if (skyrendermasked && skyrenderlater)
6569                 {
6570                         // we have to force off the water clipping plane while rendering sky
6571                         R_SetupView(false);
6572                         R_Sky();
6573                         R_SetupView(true);
6574                         if (r_timereport_active)
6575                                 R_TimeReport("sky");
6576                 }
6577         }
6578
6579         R_AnimCache_CacheVisibleEntities();
6580         if (r_timereport_active)
6581                 R_TimeReport("animation");
6582
6583         R_Shadow_PrepareLights();
6584         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6585                 R_Shadow_PrepareModelShadows();
6586         if (r_timereport_active)
6587                 R_TimeReport("preparelights");
6588
6589         if (R_Shadow_ShadowMappingEnabled())
6590                 shadowmapping = true;
6591
6592         if (r_shadow_usingdeferredprepass)
6593                 R_Shadow_DrawPrepass();
6594
6595         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6596         {
6597                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6598                 if (r_timereport_active)
6599                         R_TimeReport("worlddepth");
6600         }
6601         if (r_depthfirst.integer >= 2)
6602         {
6603                 R_DrawModelsDepth();
6604                 if (r_timereport_active)
6605                         R_TimeReport("modeldepth");
6606         }
6607
6608         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6609         {
6610                 R_DrawModelShadowMaps();
6611                 R_ResetViewRendering3D();
6612                 // don't let sound skip if going slow
6613                 if (r_refdef.scene.extraupdate)
6614                         S_ExtraUpdate ();
6615         }
6616
6617         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6618         {
6619                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6620                 if (r_timereport_active)
6621                         R_TimeReport("world");
6622         }
6623
6624         // don't let sound skip if going slow
6625         if (r_refdef.scene.extraupdate)
6626                 S_ExtraUpdate ();
6627
6628         R_DrawModels();
6629         if (r_timereport_active)
6630                 R_TimeReport("models");
6631
6632         // don't let sound skip if going slow
6633         if (r_refdef.scene.extraupdate)
6634                 S_ExtraUpdate ();
6635
6636         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6637         {
6638                 R_DrawModelShadows();
6639                 R_ResetViewRendering3D();
6640                 // don't let sound skip if going slow
6641                 if (r_refdef.scene.extraupdate)
6642                         S_ExtraUpdate ();
6643         }
6644
6645         if (!r_shadow_usingdeferredprepass)
6646         {
6647                 R_Shadow_DrawLights();
6648                 if (r_timereport_active)
6649                         R_TimeReport("rtlights");
6650         }
6651
6652         // don't let sound skip if going slow
6653         if (r_refdef.scene.extraupdate)
6654                 S_ExtraUpdate ();
6655
6656         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6657         {
6658                 R_DrawModelShadows();
6659                 R_ResetViewRendering3D();
6660                 // don't let sound skip if going slow
6661                 if (r_refdef.scene.extraupdate)
6662                         S_ExtraUpdate ();
6663         }
6664
6665         if (cl.csqc_vidvars.drawworld)
6666         {
6667                 if (cl_decals_newsystem.integer)
6668                 {
6669                         R_DrawModelDecals();
6670                         if (r_timereport_active)
6671                                 R_TimeReport("modeldecals");
6672                 }
6673                 else
6674                 {
6675                         R_DrawDecals();
6676                         if (r_timereport_active)
6677                                 R_TimeReport("decals");
6678                 }
6679
6680                 R_DrawParticles();
6681                 if (r_timereport_active)
6682                         R_TimeReport("particles");
6683
6684                 R_DrawExplosions();
6685                 if (r_timereport_active)
6686                         R_TimeReport("explosions");
6687
6688                 R_DrawLightningBeams();
6689                 if (r_timereport_active)
6690                         R_TimeReport("lightning");
6691         }
6692
6693         VM_CL_AddPolygonsToMeshQueue();
6694
6695         if (r_refdef.view.showdebug)
6696         {
6697                 if (cl_locs_show.integer)
6698                 {
6699                         R_DrawLocs();
6700                         if (r_timereport_active)
6701                                 R_TimeReport("showlocs");
6702                 }
6703
6704                 if (r_drawportals.integer)
6705                 {
6706                         R_DrawPortals();
6707                         if (r_timereport_active)
6708                                 R_TimeReport("portals");
6709                 }
6710
6711                 if (r_showbboxes.value > 0)
6712                 {
6713                         R_DrawEntityBBoxes();
6714                         if (r_timereport_active)
6715                                 R_TimeReport("bboxes");
6716                 }
6717         }
6718
6719         R_MeshQueue_RenderTransparent();
6720         if (r_timereport_active)
6721                 R_TimeReport("drawtrans");
6722
6723         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))
6724         {
6725                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6726                 if (r_timereport_active)
6727                         R_TimeReport("worlddebug");
6728                 R_DrawModelsDebug();
6729                 if (r_timereport_active)
6730                         R_TimeReport("modeldebug");
6731         }
6732
6733         if (cl.csqc_vidvars.drawworld)
6734         {
6735                 R_Shadow_DrawCoronas();
6736                 if (r_timereport_active)
6737                         R_TimeReport("coronas");
6738         }
6739
6740 #if 0
6741         {
6742                 GL_DepthTest(false);
6743                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6744                 GL_Color(1, 1, 1, 1);
6745                 qglBegin(GL_POLYGON);
6746                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6747                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6748                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6749                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6750                 qglEnd();
6751                 qglBegin(GL_POLYGON);
6752                 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]);
6753                 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]);
6754                 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]);
6755                 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]);
6756                 qglEnd();
6757                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6758         }
6759 #endif
6760
6761         // don't let sound skip if going slow
6762         if (r_refdef.scene.extraupdate)
6763                 S_ExtraUpdate ();
6764
6765         R_ResetViewRendering2D();
6766 }
6767
6768 static const unsigned short bboxelements[36] =
6769 {
6770         5, 1, 3, 5, 3, 7,
6771         6, 2, 0, 6, 0, 4,
6772         7, 3, 2, 7, 2, 6,
6773         4, 0, 1, 4, 1, 5,
6774         4, 5, 7, 4, 7, 6,
6775         1, 0, 2, 1, 2, 3,
6776 };
6777
6778 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6779 {
6780         int i;
6781         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6782
6783         RSurf_ActiveWorldEntity();
6784
6785         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6786         GL_DepthMask(false);
6787         GL_DepthRange(0, 1);
6788         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6789 //      R_Mesh_ResetTextureState();
6790
6791         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6792         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6793         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6794         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6795         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6796         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6797         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6798         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6799         R_FillColors(color4f, 8, cr, cg, cb, ca);
6800         if (r_refdef.fogenabled)
6801         {
6802                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6803                 {
6804                         f1 = RSurf_FogVertex(v);
6805                         f2 = 1 - f1;
6806                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6807                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6808                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6809                 }
6810         }
6811         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6812         R_Mesh_ResetTextureState();
6813         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6814         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6815 }
6816
6817 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6818 {
6819         int i;
6820         float color[4];
6821         prvm_edict_t *edict;
6822         prvm_prog_t *prog_save = prog;
6823
6824         // this function draws bounding boxes of server entities
6825         if (!sv.active)
6826                 return;
6827
6828         GL_CullFace(GL_NONE);
6829         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6830
6831         prog = 0;
6832         SV_VM_Begin();
6833         for (i = 0;i < numsurfaces;i++)
6834         {
6835                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6836                 switch ((int)edict->fields.server->solid)
6837                 {
6838                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6839                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6840                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6841                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6842                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6843                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6844                 }
6845                 color[3] *= r_showbboxes.value;
6846                 color[3] = bound(0, color[3], 1);
6847                 GL_DepthTest(!r_showdisabledepthtest.integer);
6848                 GL_CullFace(r_refdef.view.cullface_front);
6849                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6850         }
6851         SV_VM_End();
6852         prog = prog_save;
6853 }
6854
6855 static void R_DrawEntityBBoxes(void)
6856 {
6857         int i;
6858         prvm_edict_t *edict;
6859         vec3_t center;
6860         prvm_prog_t *prog_save = prog;
6861
6862         // this function draws bounding boxes of server entities
6863         if (!sv.active)
6864                 return;
6865
6866         prog = 0;
6867         SV_VM_Begin();
6868         for (i = 0;i < prog->num_edicts;i++)
6869         {
6870                 edict = PRVM_EDICT_NUM(i);
6871                 if (edict->priv.server->free)
6872                         continue;
6873                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6874                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6875                         continue;
6876                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6877                         continue;
6878                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6879                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6880         }
6881         SV_VM_End();
6882         prog = prog_save;
6883 }
6884
6885 static const int nomodelelement3i[24] =
6886 {
6887         5, 2, 0,
6888         5, 1, 2,
6889         5, 0, 3,
6890         5, 3, 1,
6891         0, 2, 4,
6892         2, 1, 4,
6893         3, 0, 4,
6894         1, 3, 4
6895 };
6896
6897 static const unsigned short nomodelelement3s[24] =
6898 {
6899         5, 2, 0,
6900         5, 1, 2,
6901         5, 0, 3,
6902         5, 3, 1,
6903         0, 2, 4,
6904         2, 1, 4,
6905         3, 0, 4,
6906         1, 3, 4
6907 };
6908
6909 static const float nomodelvertex3f[6*3] =
6910 {
6911         -16,   0,   0,
6912          16,   0,   0,
6913           0, -16,   0,
6914           0,  16,   0,
6915           0,   0, -16,
6916           0,   0,  16
6917 };
6918
6919 static const float nomodelcolor4f[6*4] =
6920 {
6921         0.0f, 0.0f, 0.5f, 1.0f,
6922         0.0f, 0.0f, 0.5f, 1.0f,
6923         0.0f, 0.5f, 0.0f, 1.0f,
6924         0.0f, 0.5f, 0.0f, 1.0f,
6925         0.5f, 0.0f, 0.0f, 1.0f,
6926         0.5f, 0.0f, 0.0f, 1.0f
6927 };
6928
6929 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6930 {
6931         int i;
6932         float f1, f2, *c;
6933         float color4f[6*4];
6934
6935         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);
6936
6937         // this is only called once per entity so numsurfaces is always 1, and
6938         // surfacelist is always {0}, so this code does not handle batches
6939
6940         if (rsurface.ent_flags & RENDER_ADDITIVE)
6941         {
6942                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6943                 GL_DepthMask(false);
6944         }
6945         else if (rsurface.colormod[3] < 1)
6946         {
6947                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6948                 GL_DepthMask(false);
6949         }
6950         else
6951         {
6952                 GL_BlendFunc(GL_ONE, GL_ZERO);
6953                 GL_DepthMask(true);
6954         }
6955         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6956         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6957         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6958         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6959         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6960         for (i = 0, c = color4f;i < 6;i++, c += 4)
6961         {
6962                 c[0] *= rsurface.colormod[0];
6963                 c[1] *= rsurface.colormod[1];
6964                 c[2] *= rsurface.colormod[2];
6965                 c[3] *= rsurface.colormod[3];
6966         }
6967         if (r_refdef.fogenabled)
6968         {
6969                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6970                 {
6971                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6972                         f2 = 1 - f1;
6973                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6974                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6975                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6976                 }
6977         }
6978 //      R_Mesh_ResetTextureState();
6979         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6980         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6981         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6982 }
6983
6984 void R_DrawNoModel(entity_render_t *ent)
6985 {
6986         vec3_t org;
6987         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6988         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6989                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6990         else
6991                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6992 }
6993
6994 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6995 {
6996         vec3_t right1, right2, diff, normal;
6997
6998         VectorSubtract (org2, org1, normal);
6999
7000         // calculate 'right' vector for start
7001         VectorSubtract (r_refdef.view.origin, org1, diff);
7002         CrossProduct (normal, diff, right1);
7003         VectorNormalize (right1);
7004
7005         // calculate 'right' vector for end
7006         VectorSubtract (r_refdef.view.origin, org2, diff);
7007         CrossProduct (normal, diff, right2);
7008         VectorNormalize (right2);
7009
7010         vert[ 0] = org1[0] + width * right1[0];
7011         vert[ 1] = org1[1] + width * right1[1];
7012         vert[ 2] = org1[2] + width * right1[2];
7013         vert[ 3] = org1[0] - width * right1[0];
7014         vert[ 4] = org1[1] - width * right1[1];
7015         vert[ 5] = org1[2] - width * right1[2];
7016         vert[ 6] = org2[0] - width * right2[0];
7017         vert[ 7] = org2[1] - width * right2[1];
7018         vert[ 8] = org2[2] - width * right2[2];
7019         vert[ 9] = org2[0] + width * right2[0];
7020         vert[10] = org2[1] + width * right2[1];
7021         vert[11] = org2[2] + width * right2[2];
7022 }
7023
7024 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)
7025 {
7026         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7027         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7028         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7029         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7030         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7031         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7032         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7033         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7034         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7035         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7036         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7037         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7038 }
7039
7040 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7041 {
7042         int i;
7043         float *vertex3f;
7044         float v[3];
7045         VectorSet(v, x, y, z);
7046         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7047                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7048                         break;
7049         if (i == mesh->numvertices)
7050         {
7051                 if (mesh->numvertices < mesh->maxvertices)
7052                 {
7053                         VectorCopy(v, vertex3f);
7054                         mesh->numvertices++;
7055                 }
7056                 return mesh->numvertices;
7057         }
7058         else
7059                 return i;
7060 }
7061
7062 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7063 {
7064         int i;
7065         int *e, element[3];
7066         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7067         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7068         e = mesh->element3i + mesh->numtriangles * 3;
7069         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7070         {
7071                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7072                 if (mesh->numtriangles < mesh->maxtriangles)
7073                 {
7074                         *e++ = element[0];
7075                         *e++ = element[1];
7076                         *e++ = element[2];
7077                         mesh->numtriangles++;
7078                 }
7079                 element[1] = element[2];
7080         }
7081 }
7082
7083 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7084 {
7085         int i;
7086         int *e, element[3];
7087         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7088         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7089         e = mesh->element3i + mesh->numtriangles * 3;
7090         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7091         {
7092                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7093                 if (mesh->numtriangles < mesh->maxtriangles)
7094                 {
7095                         *e++ = element[0];
7096                         *e++ = element[1];
7097                         *e++ = element[2];
7098                         mesh->numtriangles++;
7099                 }
7100                 element[1] = element[2];
7101         }
7102 }
7103
7104 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7105 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7106 {
7107         int planenum, planenum2;
7108         int w;
7109         int tempnumpoints;
7110         mplane_t *plane, *plane2;
7111         double maxdist;
7112         double temppoints[2][256*3];
7113         // figure out how large a bounding box we need to properly compute this brush
7114         maxdist = 0;
7115         for (w = 0;w < numplanes;w++)
7116                 maxdist = max(maxdist, fabs(planes[w].dist));
7117         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7118         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7119         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7120         {
7121                 w = 0;
7122                 tempnumpoints = 4;
7123                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7124                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7125                 {
7126                         if (planenum2 == planenum)
7127                                 continue;
7128                         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);
7129                         w = !w;
7130                 }
7131                 if (tempnumpoints < 3)
7132                         continue;
7133                 // generate elements forming a triangle fan for this polygon
7134                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7135         }
7136 }
7137
7138 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)
7139 {
7140         texturelayer_t *layer;
7141         layer = t->currentlayers + t->currentnumlayers++;
7142         layer->type = type;
7143         layer->depthmask = depthmask;
7144         layer->blendfunc1 = blendfunc1;
7145         layer->blendfunc2 = blendfunc2;
7146         layer->texture = texture;
7147         layer->texmatrix = *matrix;
7148         layer->color[0] = r;
7149         layer->color[1] = g;
7150         layer->color[2] = b;
7151         layer->color[3] = a;
7152 }
7153
7154 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7155 {
7156         if(parms[0] == 0 && parms[1] == 0)
7157                 return false;
7158         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7159                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7160                         return false;
7161         return true;
7162 }
7163
7164 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7165 {
7166         double index, f;
7167         index = parms[2] + r_refdef.scene.time * parms[3];
7168         index -= floor(index);
7169         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7170         {
7171         default:
7172         case Q3WAVEFUNC_NONE:
7173         case Q3WAVEFUNC_NOISE:
7174         case Q3WAVEFUNC_COUNT:
7175                 f = 0;
7176                 break;
7177         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7178         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7179         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7180         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7181         case Q3WAVEFUNC_TRIANGLE:
7182                 index *= 4;
7183                 f = index - floor(index);
7184                 if (index < 1)
7185                         f = f;
7186                 else if (index < 2)
7187                         f = 1 - f;
7188                 else if (index < 3)
7189                         f = -f;
7190                 else
7191                         f = -(1 - f);
7192                 break;
7193         }
7194         f = parms[0] + parms[1] * f;
7195         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7196                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7197         return (float) f;
7198 }
7199
7200 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7201 {
7202         int w, h, idx;
7203         float f;
7204         float tcmat[12];
7205         matrix4x4_t matrix, temp;
7206         switch(tcmod->tcmod)
7207         {
7208                 case Q3TCMOD_COUNT:
7209                 case Q3TCMOD_NONE:
7210                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7211                                 matrix = r_waterscrollmatrix;
7212                         else
7213                                 matrix = identitymatrix;
7214                         break;
7215                 case Q3TCMOD_ENTITYTRANSLATE:
7216                         // this is used in Q3 to allow the gamecode to control texcoord
7217                         // scrolling on the entity, which is not supported in darkplaces yet.
7218                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7219                         break;
7220                 case Q3TCMOD_ROTATE:
7221                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7222                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7223                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7224                         break;
7225                 case Q3TCMOD_SCALE:
7226                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7227                         break;
7228                 case Q3TCMOD_SCROLL:
7229                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7230                         break;
7231                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7232                         w = (int) tcmod->parms[0];
7233                         h = (int) tcmod->parms[1];
7234                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7235                         f = f - floor(f);
7236                         idx = (int) floor(f * w * h);
7237                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7238                         break;
7239                 case Q3TCMOD_STRETCH:
7240                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7241                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7242                         break;
7243                 case Q3TCMOD_TRANSFORM:
7244                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7245                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7246                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7247                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7248                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7249                         break;
7250                 case Q3TCMOD_TURBULENT:
7251                         // this is handled in the RSurf_PrepareVertices function
7252                         matrix = identitymatrix;
7253                         break;
7254         }
7255         temp = *texmatrix;
7256         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7257 }
7258
7259 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7260 {
7261         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7262         char name[MAX_QPATH];
7263         skinframe_t *skinframe;
7264         unsigned char pixels[296*194];
7265         strlcpy(cache->name, skinname, sizeof(cache->name));
7266         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7267         if (developer_loading.integer)
7268                 Con_Printf("loading %s\n", name);
7269         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7270         if (!skinframe || !skinframe->base)
7271         {
7272                 unsigned char *f;
7273                 fs_offset_t filesize;
7274                 skinframe = NULL;
7275                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7276                 if (f)
7277                 {
7278                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7279                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7280                         Mem_Free(f);
7281                 }
7282         }
7283         cache->skinframe = skinframe;
7284 }
7285
7286 texture_t *R_GetCurrentTexture(texture_t *t)
7287 {
7288         int i;
7289         const entity_render_t *ent = rsurface.entity;
7290         dp_model_t *model = ent->model;
7291         q3shaderinfo_layer_tcmod_t *tcmod;
7292
7293         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7294                 return t->currentframe;
7295         t->update_lastrenderframe = r_textureframe;
7296         t->update_lastrenderentity = (void *)ent;
7297
7298         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7299                 t->camera_entity = ent->entitynumber;
7300         else
7301                 t->camera_entity = 0;
7302
7303         // switch to an alternate material if this is a q1bsp animated material
7304         {
7305                 texture_t *texture = t;
7306                 int s = rsurface.ent_skinnum;
7307                 if ((unsigned int)s >= (unsigned int)model->numskins)
7308                         s = 0;
7309                 if (model->skinscenes)
7310                 {
7311                         if (model->skinscenes[s].framecount > 1)
7312                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7313                         else
7314                                 s = model->skinscenes[s].firstframe;
7315                 }
7316                 if (s > 0)
7317                         t = t + s * model->num_surfaces;
7318                 if (t->animated)
7319                 {
7320                         // use an alternate animation if the entity's frame is not 0,
7321                         // and only if the texture has an alternate animation
7322                         if (rsurface.ent_alttextures && t->anim_total[1])
7323                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7324                         else
7325                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7326                 }
7327                 texture->currentframe = t;
7328         }
7329
7330         // update currentskinframe to be a qw skin or animation frame
7331         if (rsurface.ent_qwskin >= 0)
7332         {
7333                 i = rsurface.ent_qwskin;
7334                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7335                 {
7336                         r_qwskincache_size = cl.maxclients;
7337                         if (r_qwskincache)
7338                                 Mem_Free(r_qwskincache);
7339                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7340                 }
7341                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7342                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7343                 t->currentskinframe = r_qwskincache[i].skinframe;
7344                 if (t->currentskinframe == NULL)
7345                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7346         }
7347         else if (t->numskinframes >= 2)
7348                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7349         if (t->backgroundnumskinframes >= 2)
7350                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7351
7352         t->currentmaterialflags = t->basematerialflags;
7353         t->currentalpha = rsurface.colormod[3];
7354         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7355                 t->currentalpha *= r_wateralpha.value;
7356         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7357                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7358         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7359                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7360         if (!(rsurface.ent_flags & RENDER_LIGHT))
7361                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7362         else if (FAKELIGHT_ENABLED)
7363         {
7364                         // no modellight if using fakelight for the map
7365         }
7366         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7367         {
7368                 // pick a model lighting mode
7369                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7370                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7371                 else
7372                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7373         }
7374         if (rsurface.ent_flags & RENDER_ADDITIVE)
7375                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7376         else if (t->currentalpha < 1)
7377                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7378         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7379                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7380         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7381                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7382         if (t->backgroundnumskinframes)
7383                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7384         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7385         {
7386                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7387                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7388         }
7389         else
7390                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7391         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7392                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7393
7394         // there is no tcmod
7395         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7396         {
7397                 t->currenttexmatrix = r_waterscrollmatrix;
7398                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7399         }
7400         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7401         {
7402                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7403                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7404         }
7405
7406         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7407                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7408         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7409                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7410
7411         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7412         if (t->currentskinframe->qpixels)
7413                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7414         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7415         if (!t->basetexture)
7416                 t->basetexture = r_texture_notexture;
7417         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7418         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7419         t->nmaptexture = t->currentskinframe->nmap;
7420         if (!t->nmaptexture)
7421                 t->nmaptexture = r_texture_blanknormalmap;
7422         t->glosstexture = r_texture_black;
7423         t->glowtexture = t->currentskinframe->glow;
7424         t->fogtexture = t->currentskinframe->fog;
7425         t->reflectmasktexture = t->currentskinframe->reflect;
7426         if (t->backgroundnumskinframes)
7427         {
7428                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7429                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7430                 t->backgroundglosstexture = r_texture_black;
7431                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7432                 if (!t->backgroundnmaptexture)
7433                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7434         }
7435         else
7436         {
7437                 t->backgroundbasetexture = r_texture_white;
7438                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7439                 t->backgroundglosstexture = r_texture_black;
7440                 t->backgroundglowtexture = NULL;
7441         }
7442         t->specularpower = r_shadow_glossexponent.value;
7443         // TODO: store reference values for these in the texture?
7444         t->specularscale = 0;
7445         if (r_shadow_gloss.integer > 0)
7446         {
7447                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7448                 {
7449                         if (r_shadow_glossintensity.value > 0)
7450                         {
7451                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7452                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7453                                 t->specularscale = r_shadow_glossintensity.value;
7454                         }
7455                 }
7456                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7457                 {
7458                         t->glosstexture = r_texture_white;
7459                         t->backgroundglosstexture = r_texture_white;
7460                         t->specularscale = r_shadow_gloss2intensity.value;
7461                         t->specularpower = r_shadow_gloss2exponent.value;
7462                 }
7463         }
7464         t->specularscale *= t->specularscalemod;
7465         t->specularpower *= t->specularpowermod;
7466
7467         // lightmaps mode looks bad with dlights using actual texturing, so turn
7468         // off the colormap and glossmap, but leave the normalmap on as it still
7469         // accurately represents the shading involved
7470         if (gl_lightmaps.integer)
7471         {
7472                 t->basetexture = r_texture_grey128;
7473                 t->pantstexture = r_texture_black;
7474                 t->shirttexture = r_texture_black;
7475                 t->nmaptexture = r_texture_blanknormalmap;
7476                 t->glosstexture = r_texture_black;
7477                 t->glowtexture = NULL;
7478                 t->fogtexture = NULL;
7479                 t->reflectmasktexture = NULL;
7480                 t->backgroundbasetexture = NULL;
7481                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7482                 t->backgroundglosstexture = r_texture_black;
7483                 t->backgroundglowtexture = NULL;
7484                 t->specularscale = 0;
7485                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7486         }
7487
7488         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7489         VectorClear(t->dlightcolor);
7490         t->currentnumlayers = 0;
7491         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7492         {
7493                 int blendfunc1, blendfunc2;
7494                 qboolean depthmask;
7495                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7496                 {
7497                         blendfunc1 = GL_SRC_ALPHA;
7498                         blendfunc2 = GL_ONE;
7499                 }
7500                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7501                 {
7502                         blendfunc1 = GL_SRC_ALPHA;
7503                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7504                 }
7505                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7506                 {
7507                         blendfunc1 = t->customblendfunc[0];
7508                         blendfunc2 = t->customblendfunc[1];
7509                 }
7510                 else
7511                 {
7512                         blendfunc1 = GL_ONE;
7513                         blendfunc2 = GL_ZERO;
7514                 }
7515                 // don't colormod evilblend textures
7516                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7517                         VectorSet(t->lightmapcolor, 1, 1, 1);
7518                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7519                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7520                 {
7521                         // fullbright is not affected by r_refdef.lightmapintensity
7522                         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]);
7523                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7524                                 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]);
7525                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7526                                 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]);
7527                 }
7528                 else
7529                 {
7530                         vec3_t ambientcolor;
7531                         float colorscale;
7532                         // set the color tint used for lights affecting this surface
7533                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7534                         colorscale = 2;
7535                         // q3bsp has no lightmap updates, so the lightstylevalue that
7536                         // would normally be baked into the lightmap must be
7537                         // applied to the color
7538                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7539                         if (model->type == mod_brushq3)
7540                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7541                         colorscale *= r_refdef.lightmapintensity;
7542                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7543                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7544                         // basic lit geometry
7545                         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]);
7546                         // add pants/shirt if needed
7547                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7548                                 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]);
7549                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7550                                 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]);
7551                         // now add ambient passes if needed
7552                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7553                         {
7554                                 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]);
7555                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7556                                         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]);
7557                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7558                                         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]);
7559                         }
7560                 }
7561                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7562                         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]);
7563                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7564                 {
7565                         // if this is opaque use alpha blend which will darken the earlier
7566                         // passes cheaply.
7567                         //
7568                         // if this is an alpha blended material, all the earlier passes
7569                         // were darkened by fog already, so we only need to add the fog
7570                         // color ontop through the fog mask texture
7571                         //
7572                         // if this is an additive blended material, all the earlier passes
7573                         // were darkened by fog already, and we should not add fog color
7574                         // (because the background was not darkened, there is no fog color
7575                         // that was lost behind it).
7576                         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]);
7577                 }
7578         }
7579
7580         return t->currentframe;
7581 }
7582
7583 rsurfacestate_t rsurface;
7584
7585 void RSurf_ActiveWorldEntity(void)
7586 {
7587         dp_model_t *model = r_refdef.scene.worldmodel;
7588         //if (rsurface.entity == r_refdef.scene.worldentity)
7589         //      return;
7590         rsurface.entity = r_refdef.scene.worldentity;
7591         rsurface.skeleton = NULL;
7592         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7593         rsurface.ent_skinnum = 0;
7594         rsurface.ent_qwskin = -1;
7595         rsurface.ent_shadertime = 0;
7596         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7597         rsurface.matrix = identitymatrix;
7598         rsurface.inversematrix = identitymatrix;
7599         rsurface.matrixscale = 1;
7600         rsurface.inversematrixscale = 1;
7601         R_EntityMatrix(&identitymatrix);
7602         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7603         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7604         rsurface.fograngerecip = r_refdef.fograngerecip;
7605         rsurface.fogheightfade = r_refdef.fogheightfade;
7606         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7607         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7608         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7609         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7610         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7611         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7612         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7613         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7614         rsurface.colormod[3] = 1;
7615         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);
7616         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7617         rsurface.frameblend[0].lerp = 1;
7618         rsurface.ent_alttextures = false;
7619         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7620         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7621         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7622         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7623         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7624         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7625         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7626         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7627         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7628         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7629         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7630         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7631         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7632         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7633         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7634         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7635         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7636         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7637         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7638         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7639         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7640         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7641         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7642         rsurface.modelelement3i = model->surfmesh.data_element3i;
7643         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7644         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7645         rsurface.modelelement3s = model->surfmesh.data_element3s;
7646         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7647         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7648         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7649         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7650         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7651         rsurface.modelsurfaces = model->data_surfaces;
7652         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7653         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7654         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7655         rsurface.modelgeneratedvertex = false;
7656         rsurface.batchgeneratedvertex = false;
7657         rsurface.batchfirstvertex = 0;
7658         rsurface.batchnumvertices = 0;
7659         rsurface.batchfirsttriangle = 0;
7660         rsurface.batchnumtriangles = 0;
7661         rsurface.batchvertex3f  = NULL;
7662         rsurface.batchvertex3f_vertexbuffer = NULL;
7663         rsurface.batchvertex3f_bufferoffset = 0;
7664         rsurface.batchsvector3f = NULL;
7665         rsurface.batchsvector3f_vertexbuffer = NULL;
7666         rsurface.batchsvector3f_bufferoffset = 0;
7667         rsurface.batchtvector3f = NULL;
7668         rsurface.batchtvector3f_vertexbuffer = NULL;
7669         rsurface.batchtvector3f_bufferoffset = 0;
7670         rsurface.batchnormal3f  = NULL;
7671         rsurface.batchnormal3f_vertexbuffer = NULL;
7672         rsurface.batchnormal3f_bufferoffset = 0;
7673         rsurface.batchlightmapcolor4f = NULL;
7674         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7675         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7676         rsurface.batchtexcoordtexture2f = NULL;
7677         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7678         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7679         rsurface.batchtexcoordlightmap2f = NULL;
7680         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7681         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7682         rsurface.batchvertexmesh = NULL;
7683         rsurface.batchvertexmeshbuffer = NULL;
7684         rsurface.batchvertex3fbuffer = NULL;
7685         rsurface.batchelement3i = NULL;
7686         rsurface.batchelement3i_indexbuffer = NULL;
7687         rsurface.batchelement3i_bufferoffset = 0;
7688         rsurface.batchelement3s = NULL;
7689         rsurface.batchelement3s_indexbuffer = NULL;
7690         rsurface.batchelement3s_bufferoffset = 0;
7691         rsurface.passcolor4f = NULL;
7692         rsurface.passcolor4f_vertexbuffer = NULL;
7693         rsurface.passcolor4f_bufferoffset = 0;
7694 }
7695
7696 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7697 {
7698         dp_model_t *model = ent->model;
7699         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7700         //      return;
7701         rsurface.entity = (entity_render_t *)ent;
7702         rsurface.skeleton = ent->skeleton;
7703         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7704         rsurface.ent_skinnum = ent->skinnum;
7705         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;
7706         rsurface.ent_shadertime = ent->shadertime;
7707         rsurface.ent_flags = ent->flags;
7708         rsurface.matrix = ent->matrix;
7709         rsurface.inversematrix = ent->inversematrix;
7710         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7711         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7712         R_EntityMatrix(&rsurface.matrix);
7713         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7714         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7715         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7716         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7717         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7718         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7719         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7720         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7721         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7722         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7723         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7724         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7725         rsurface.colormod[3] = ent->alpha;
7726         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7727         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7728         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7729         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7730         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7731         if (ent->model->brush.submodel && !prepass)
7732         {
7733                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7734                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7735         }
7736         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7737         {
7738                 if (ent->animcache_vertex3f)
7739                 {
7740                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7741                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7742                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7743                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7744                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7745                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7746                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7747                 }
7748                 else if (wanttangents)
7749                 {
7750                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7751                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7752                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7753                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7754                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7755                         rsurface.modelvertexmesh = NULL;
7756                         rsurface.modelvertexmeshbuffer = NULL;
7757                         rsurface.modelvertex3fbuffer = NULL;
7758                 }
7759                 else if (wantnormals)
7760                 {
7761                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7762                         rsurface.modelsvector3f = NULL;
7763                         rsurface.modeltvector3f = NULL;
7764                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7765                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7766                         rsurface.modelvertexmesh = NULL;
7767                         rsurface.modelvertexmeshbuffer = NULL;
7768                         rsurface.modelvertex3fbuffer = NULL;
7769                 }
7770                 else
7771                 {
7772                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7773                         rsurface.modelsvector3f = NULL;
7774                         rsurface.modeltvector3f = NULL;
7775                         rsurface.modelnormal3f = NULL;
7776                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7777                         rsurface.modelvertexmesh = NULL;
7778                         rsurface.modelvertexmeshbuffer = NULL;
7779                         rsurface.modelvertex3fbuffer = NULL;
7780                 }
7781                 rsurface.modelvertex3f_vertexbuffer = 0;
7782                 rsurface.modelvertex3f_bufferoffset = 0;
7783                 rsurface.modelsvector3f_vertexbuffer = 0;
7784                 rsurface.modelsvector3f_bufferoffset = 0;
7785                 rsurface.modeltvector3f_vertexbuffer = 0;
7786                 rsurface.modeltvector3f_bufferoffset = 0;
7787                 rsurface.modelnormal3f_vertexbuffer = 0;
7788                 rsurface.modelnormal3f_bufferoffset = 0;
7789                 rsurface.modelgeneratedvertex = true;
7790         }
7791         else
7792         {
7793                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7794                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7795                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7796                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7797                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7798                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7799                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7800                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7801                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7802                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7803                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7804                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7805                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7806                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7807                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7808                 rsurface.modelgeneratedvertex = false;
7809         }
7810         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7811         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7812         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7813         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7814         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7815         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7816         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7817         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7818         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7819         rsurface.modelelement3i = model->surfmesh.data_element3i;
7820         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7821         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7822         rsurface.modelelement3s = model->surfmesh.data_element3s;
7823         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7824         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7825         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7826         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7827         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7828         rsurface.modelsurfaces = model->data_surfaces;
7829         rsurface.batchgeneratedvertex = false;
7830         rsurface.batchfirstvertex = 0;
7831         rsurface.batchnumvertices = 0;
7832         rsurface.batchfirsttriangle = 0;
7833         rsurface.batchnumtriangles = 0;
7834         rsurface.batchvertex3f  = NULL;
7835         rsurface.batchvertex3f_vertexbuffer = NULL;
7836         rsurface.batchvertex3f_bufferoffset = 0;
7837         rsurface.batchsvector3f = NULL;
7838         rsurface.batchsvector3f_vertexbuffer = NULL;
7839         rsurface.batchsvector3f_bufferoffset = 0;
7840         rsurface.batchtvector3f = NULL;
7841         rsurface.batchtvector3f_vertexbuffer = NULL;
7842         rsurface.batchtvector3f_bufferoffset = 0;
7843         rsurface.batchnormal3f  = NULL;
7844         rsurface.batchnormal3f_vertexbuffer = NULL;
7845         rsurface.batchnormal3f_bufferoffset = 0;
7846         rsurface.batchlightmapcolor4f = NULL;
7847         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7848         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7849         rsurface.batchtexcoordtexture2f = NULL;
7850         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7851         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7852         rsurface.batchtexcoordlightmap2f = NULL;
7853         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7854         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7855         rsurface.batchvertexmesh = NULL;
7856         rsurface.batchvertexmeshbuffer = NULL;
7857         rsurface.batchvertex3fbuffer = NULL;
7858         rsurface.batchelement3i = NULL;
7859         rsurface.batchelement3i_indexbuffer = NULL;
7860         rsurface.batchelement3i_bufferoffset = 0;
7861         rsurface.batchelement3s = NULL;
7862         rsurface.batchelement3s_indexbuffer = NULL;
7863         rsurface.batchelement3s_bufferoffset = 0;
7864         rsurface.passcolor4f = NULL;
7865         rsurface.passcolor4f_vertexbuffer = NULL;
7866         rsurface.passcolor4f_bufferoffset = 0;
7867 }
7868
7869 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)
7870 {
7871         rsurface.entity = r_refdef.scene.worldentity;
7872         rsurface.skeleton = NULL;
7873         rsurface.ent_skinnum = 0;
7874         rsurface.ent_qwskin = -1;
7875         rsurface.ent_shadertime = shadertime;
7876         rsurface.ent_flags = entflags;
7877         rsurface.modelnumvertices = numvertices;
7878         rsurface.modelnumtriangles = numtriangles;
7879         rsurface.matrix = *matrix;
7880         rsurface.inversematrix = *inversematrix;
7881         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7882         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7883         R_EntityMatrix(&rsurface.matrix);
7884         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7885         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7886         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7887         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7888         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7889         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7890         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7891         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7892         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7893         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7894         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7895         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7896         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);
7897         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7898         rsurface.frameblend[0].lerp = 1;
7899         rsurface.ent_alttextures = false;
7900         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7901         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7902         if (wanttangents)
7903         {
7904                 rsurface.modelvertex3f = (float *)vertex3f;
7905                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7906                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7907                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7908         }
7909         else if (wantnormals)
7910         {
7911                 rsurface.modelvertex3f = (float *)vertex3f;
7912                 rsurface.modelsvector3f = NULL;
7913                 rsurface.modeltvector3f = NULL;
7914                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7915         }
7916         else
7917         {
7918                 rsurface.modelvertex3f = (float *)vertex3f;
7919                 rsurface.modelsvector3f = NULL;
7920                 rsurface.modeltvector3f = NULL;
7921                 rsurface.modelnormal3f = NULL;
7922         }
7923         rsurface.modelvertexmesh = NULL;
7924         rsurface.modelvertexmeshbuffer = NULL;
7925         rsurface.modelvertex3fbuffer = NULL;
7926         rsurface.modelvertex3f_vertexbuffer = 0;
7927         rsurface.modelvertex3f_bufferoffset = 0;
7928         rsurface.modelsvector3f_vertexbuffer = 0;
7929         rsurface.modelsvector3f_bufferoffset = 0;
7930         rsurface.modeltvector3f_vertexbuffer = 0;
7931         rsurface.modeltvector3f_bufferoffset = 0;
7932         rsurface.modelnormal3f_vertexbuffer = 0;
7933         rsurface.modelnormal3f_bufferoffset = 0;
7934         rsurface.modelgeneratedvertex = true;
7935         rsurface.modellightmapcolor4f  = (float *)color4f;
7936         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7937         rsurface.modellightmapcolor4f_bufferoffset = 0;
7938         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7939         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7940         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7941         rsurface.modeltexcoordlightmap2f  = NULL;
7942         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7943         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7944         rsurface.modelelement3i = (int *)element3i;
7945         rsurface.modelelement3i_indexbuffer = NULL;
7946         rsurface.modelelement3i_bufferoffset = 0;
7947         rsurface.modelelement3s = (unsigned short *)element3s;
7948         rsurface.modelelement3s_indexbuffer = NULL;
7949         rsurface.modelelement3s_bufferoffset = 0;
7950         rsurface.modellightmapoffsets = NULL;
7951         rsurface.modelsurfaces = NULL;
7952         rsurface.batchgeneratedvertex = false;
7953         rsurface.batchfirstvertex = 0;
7954         rsurface.batchnumvertices = 0;
7955         rsurface.batchfirsttriangle = 0;
7956         rsurface.batchnumtriangles = 0;
7957         rsurface.batchvertex3f  = NULL;
7958         rsurface.batchvertex3f_vertexbuffer = NULL;
7959         rsurface.batchvertex3f_bufferoffset = 0;
7960         rsurface.batchsvector3f = NULL;
7961         rsurface.batchsvector3f_vertexbuffer = NULL;
7962         rsurface.batchsvector3f_bufferoffset = 0;
7963         rsurface.batchtvector3f = NULL;
7964         rsurface.batchtvector3f_vertexbuffer = NULL;
7965         rsurface.batchtvector3f_bufferoffset = 0;
7966         rsurface.batchnormal3f  = NULL;
7967         rsurface.batchnormal3f_vertexbuffer = NULL;
7968         rsurface.batchnormal3f_bufferoffset = 0;
7969         rsurface.batchlightmapcolor4f = NULL;
7970         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7971         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7972         rsurface.batchtexcoordtexture2f = NULL;
7973         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7974         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7975         rsurface.batchtexcoordlightmap2f = NULL;
7976         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7977         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7978         rsurface.batchvertexmesh = NULL;
7979         rsurface.batchvertexmeshbuffer = NULL;
7980         rsurface.batchvertex3fbuffer = NULL;
7981         rsurface.batchelement3i = NULL;
7982         rsurface.batchelement3i_indexbuffer = NULL;
7983         rsurface.batchelement3i_bufferoffset = 0;
7984         rsurface.batchelement3s = NULL;
7985         rsurface.batchelement3s_indexbuffer = NULL;
7986         rsurface.batchelement3s_bufferoffset = 0;
7987         rsurface.passcolor4f = NULL;
7988         rsurface.passcolor4f_vertexbuffer = NULL;
7989         rsurface.passcolor4f_bufferoffset = 0;
7990
7991         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7992         {
7993                 if ((wantnormals || wanttangents) && !normal3f)
7994                 {
7995                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7996                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7997                 }
7998                 if (wanttangents && !svector3f)
7999                 {
8000                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8001                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8002                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8003                 }
8004         }
8005 }
8006
8007 float RSurf_FogPoint(const float *v)
8008 {
8009         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8010         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8011         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8012         float FogHeightFade = r_refdef.fogheightfade;
8013         float fogfrac;
8014         unsigned int fogmasktableindex;
8015         if (r_refdef.fogplaneviewabove)
8016                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8017         else
8018                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8019         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8020         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8021 }
8022
8023 float RSurf_FogVertex(const float *v)
8024 {
8025         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8026         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8027         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8028         float FogHeightFade = rsurface.fogheightfade;
8029         float fogfrac;
8030         unsigned int fogmasktableindex;
8031         if (r_refdef.fogplaneviewabove)
8032                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8033         else
8034                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8035         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8036         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8037 }
8038
8039 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8040 {
8041         int i;
8042         for (i = 0;i < numelements;i++)
8043                 outelement3i[i] = inelement3i[i] + adjust;
8044 }
8045
8046 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8047 extern cvar_t gl_vbo;
8048 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8049 {
8050         int deformindex;
8051         int firsttriangle;
8052         int numtriangles;
8053         int firstvertex;
8054         int endvertex;
8055         int numvertices;
8056         int surfacefirsttriangle;
8057         int surfacenumtriangles;
8058         int surfacefirstvertex;
8059         int surfaceendvertex;
8060         int surfacenumvertices;
8061         int batchnumvertices;
8062         int batchnumtriangles;
8063         int needsupdate;
8064         int i, j;
8065         qboolean gaps;
8066         qboolean dynamicvertex;
8067         float amplitude;
8068         float animpos;
8069         float scale;
8070         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8071         float waveparms[4];
8072         q3shaderinfo_deform_t *deform;
8073         const msurface_t *surface, *firstsurface;
8074         r_vertexmesh_t *vertexmesh;
8075         if (!texturenumsurfaces)
8076                 return;
8077         // find vertex range of this surface batch
8078         gaps = false;
8079         firstsurface = texturesurfacelist[0];
8080         firsttriangle = firstsurface->num_firsttriangle;
8081         batchnumvertices = 0;
8082         batchnumtriangles = 0;
8083         firstvertex = endvertex = firstsurface->num_firstvertex;
8084         for (i = 0;i < texturenumsurfaces;i++)
8085         {
8086                 surface = texturesurfacelist[i];
8087                 if (surface != firstsurface + i)
8088                         gaps = true;
8089                 surfacefirstvertex = surface->num_firstvertex;
8090                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8091                 surfacenumvertices = surface->num_vertices;
8092                 surfacenumtriangles = surface->num_triangles;
8093                 if (firstvertex > surfacefirstvertex)
8094                         firstvertex = surfacefirstvertex;
8095                 if (endvertex < surfaceendvertex)
8096                         endvertex = surfaceendvertex;
8097                 batchnumvertices += surfacenumvertices;
8098                 batchnumtriangles += surfacenumtriangles;
8099         }
8100
8101         // we now know the vertex range used, and if there are any gaps in it
8102         rsurface.batchfirstvertex = firstvertex;
8103         rsurface.batchnumvertices = endvertex - firstvertex;
8104         rsurface.batchfirsttriangle = firsttriangle;
8105         rsurface.batchnumtriangles = batchnumtriangles;
8106
8107         // this variable holds flags for which properties have been updated that
8108         // may require regenerating vertexmesh array...
8109         needsupdate = 0;
8110
8111         // check if any dynamic vertex processing must occur
8112         dynamicvertex = false;
8113
8114         // if there is a chance of animated vertex colors, it's a dynamic batch
8115         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8116         {
8117                 dynamicvertex = true;
8118                 batchneed |= BATCHNEED_NOGAPS;
8119                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8120         }
8121
8122         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8123         {
8124                 switch (deform->deform)
8125                 {
8126                 default:
8127                 case Q3DEFORM_PROJECTIONSHADOW:
8128                 case Q3DEFORM_TEXT0:
8129                 case Q3DEFORM_TEXT1:
8130                 case Q3DEFORM_TEXT2:
8131                 case Q3DEFORM_TEXT3:
8132                 case Q3DEFORM_TEXT4:
8133                 case Q3DEFORM_TEXT5:
8134                 case Q3DEFORM_TEXT6:
8135                 case Q3DEFORM_TEXT7:
8136                 case Q3DEFORM_NONE:
8137                         break;
8138                 case Q3DEFORM_AUTOSPRITE:
8139                         dynamicvertex = true;
8140                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8141                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8142                         break;
8143                 case Q3DEFORM_AUTOSPRITE2:
8144                         dynamicvertex = true;
8145                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8146                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8147                         break;
8148                 case Q3DEFORM_NORMAL:
8149                         dynamicvertex = true;
8150                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8151                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8152                         break;
8153                 case Q3DEFORM_WAVE:
8154                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8155                                 break; // if wavefunc is a nop, ignore this transform
8156                         dynamicvertex = true;
8157                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8158                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8159                         break;
8160                 case Q3DEFORM_BULGE:
8161                         dynamicvertex = true;
8162                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8163                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8164                         break;
8165                 case Q3DEFORM_MOVE:
8166                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8167                                 break; // if wavefunc is a nop, ignore this transform
8168                         dynamicvertex = true;
8169                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8170                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8171                         break;
8172                 }
8173         }
8174         switch(rsurface.texture->tcgen.tcgen)
8175         {
8176         default:
8177         case Q3TCGEN_TEXTURE:
8178                 break;
8179         case Q3TCGEN_LIGHTMAP:
8180                 dynamicvertex = true;
8181                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8182                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8183                 break;
8184         case Q3TCGEN_VECTOR:
8185                 dynamicvertex = true;
8186                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8187                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8188                 break;
8189         case Q3TCGEN_ENVIRONMENT:
8190                 dynamicvertex = true;
8191                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8192                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8193                 break;
8194         }
8195         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8196         {
8197                 dynamicvertex = true;
8198                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8199                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8200         }
8201
8202         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8203         {
8204                 dynamicvertex = true;
8205                 batchneed |= BATCHNEED_NOGAPS;
8206                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8207         }
8208
8209         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8210         {
8211                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8212                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8213                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8214                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8215                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8216                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8217                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8218         }
8219
8220         // when the model data has no vertex buffer (dynamic mesh), we need to
8221         // eliminate gaps
8222         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8223                 batchneed |= BATCHNEED_NOGAPS;
8224
8225         // if needsupdate, we have to do a dynamic vertex batch for sure
8226         if (needsupdate & batchneed)
8227                 dynamicvertex = true;
8228
8229         // see if we need to build vertexmesh from arrays
8230         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8231                 dynamicvertex = true;
8232
8233         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8234         // also some drivers strongly dislike firstvertex
8235         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8236                 dynamicvertex = true;
8237
8238         rsurface.batchvertex3f = rsurface.modelvertex3f;
8239         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8240         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8241         rsurface.batchsvector3f = rsurface.modelsvector3f;
8242         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8243         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8244         rsurface.batchtvector3f = rsurface.modeltvector3f;
8245         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8246         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8247         rsurface.batchnormal3f = rsurface.modelnormal3f;
8248         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8249         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8250         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8251         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8252         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8253         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8254         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8255         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8256         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8257         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8258         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8259         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8260         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8261         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8262         rsurface.batchelement3i = rsurface.modelelement3i;
8263         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8264         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8265         rsurface.batchelement3s = rsurface.modelelement3s;
8266         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8267         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8268
8269         // if any dynamic vertex processing has to occur in software, we copy the
8270         // entire surface list together before processing to rebase the vertices
8271         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8272         //
8273         // if any gaps exist and we do not have a static vertex buffer, we have to
8274         // copy the surface list together to avoid wasting upload bandwidth on the
8275         // vertices in the gaps.
8276         //
8277         // if gaps exist and we have a static vertex buffer, we still have to
8278         // combine the index buffer ranges into one dynamic index buffer.
8279         //
8280         // in all cases we end up with data that can be drawn in one call.
8281
8282         if (!dynamicvertex)
8283         {
8284                 // static vertex data, just set pointers...
8285                 rsurface.batchgeneratedvertex = false;
8286                 // if there are gaps, we want to build a combined index buffer,
8287                 // otherwise use the original static buffer with an appropriate offset
8288                 if (gaps)
8289                 {
8290                         // build a new triangle elements array for this batch
8291                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8292                         rsurface.batchfirsttriangle = 0;
8293                         numtriangles = 0;
8294                         for (i = 0;i < texturenumsurfaces;i++)
8295                         {
8296                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8297                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8298                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8299                                 numtriangles += surfacenumtriangles;
8300                         }
8301                         rsurface.batchelement3i_indexbuffer = NULL;
8302                         rsurface.batchelement3i_bufferoffset = 0;
8303                         rsurface.batchelement3s = NULL;
8304                         rsurface.batchelement3s_indexbuffer = NULL;
8305                         rsurface.batchelement3s_bufferoffset = 0;
8306                         if (endvertex <= 65536)
8307                         {
8308                                 // make a 16bit (unsigned short) index array if possible
8309                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8310                                 for (i = 0;i < numtriangles*3;i++)
8311                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8312                         }
8313                 }
8314                 return;
8315         }
8316
8317         // something needs software processing, do it for real...
8318         // we only directly handle separate array data in this case and then
8319         // generate interleaved data if needed...
8320         rsurface.batchgeneratedvertex = true;
8321
8322         // now copy the vertex data into a combined array and make an index array
8323         // (this is what Quake3 does all the time)
8324         //if (gaps || rsurface.batchfirstvertex)
8325         {
8326                 rsurface.batchvertex3fbuffer = NULL;
8327                 rsurface.batchvertexmesh = NULL;
8328                 rsurface.batchvertexmeshbuffer = NULL;
8329                 rsurface.batchvertex3f = NULL;
8330                 rsurface.batchvertex3f_vertexbuffer = NULL;
8331                 rsurface.batchvertex3f_bufferoffset = 0;
8332                 rsurface.batchsvector3f = NULL;
8333                 rsurface.batchsvector3f_vertexbuffer = NULL;
8334                 rsurface.batchsvector3f_bufferoffset = 0;
8335                 rsurface.batchtvector3f = NULL;
8336                 rsurface.batchtvector3f_vertexbuffer = NULL;
8337                 rsurface.batchtvector3f_bufferoffset = 0;
8338                 rsurface.batchnormal3f = NULL;
8339                 rsurface.batchnormal3f_vertexbuffer = NULL;
8340                 rsurface.batchnormal3f_bufferoffset = 0;
8341                 rsurface.batchlightmapcolor4f = NULL;
8342                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8343                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8344                 rsurface.batchtexcoordtexture2f = NULL;
8345                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8346                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8347                 rsurface.batchtexcoordlightmap2f = NULL;
8348                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8349                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8350                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8351                 rsurface.batchelement3i_indexbuffer = NULL;
8352                 rsurface.batchelement3i_bufferoffset = 0;
8353                 rsurface.batchelement3s = NULL;
8354                 rsurface.batchelement3s_indexbuffer = NULL;
8355                 rsurface.batchelement3s_bufferoffset = 0;
8356                 // we'll only be setting up certain arrays as needed
8357                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8358                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8359                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8360                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8361                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8362                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8363                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8364                 {
8365                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8366                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8367                 }
8368                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8369                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8370                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8371                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8372                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8373                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8374                 numvertices = 0;
8375                 numtriangles = 0;
8376                 for (i = 0;i < texturenumsurfaces;i++)
8377                 {
8378                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8379                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8380                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8381                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8382                         // copy only the data requested
8383                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8384                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8385                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8386                         {
8387                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8388                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8389                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8390                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8391                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8392                                 {
8393                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8394                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8395                                 }
8396                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8397                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8398                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8399                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8400                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8401                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8402                         }
8403                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8404                         numvertices += surfacenumvertices;
8405                         numtriangles += surfacenumtriangles;
8406                 }
8407
8408                 // generate a 16bit index array as well if possible
8409                 // (in general, dynamic batches fit)
8410                 if (numvertices <= 65536)
8411                 {
8412                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8413                         for (i = 0;i < numtriangles*3;i++)
8414                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8415                 }
8416
8417                 // since we've copied everything, the batch now starts at 0
8418                 rsurface.batchfirstvertex = 0;
8419                 rsurface.batchnumvertices = batchnumvertices;
8420                 rsurface.batchfirsttriangle = 0;
8421                 rsurface.batchnumtriangles = batchnumtriangles;
8422         }
8423
8424         // q1bsp surfaces rendered in vertex color mode have to have colors
8425         // calculated based on lightstyles
8426         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8427         {
8428                 // generate color arrays for the surfaces in this list
8429                 int c[4];
8430                 int scale;
8431                 int size3;
8432                 const int *offsets;
8433                 const unsigned char *lm;
8434                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8435                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8436                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8437                 numvertices = 0;
8438                 for (i = 0;i < texturenumsurfaces;i++)
8439                 {
8440                         surface = texturesurfacelist[i];
8441                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8442                         surfacenumvertices = surface->num_vertices;
8443                         if (surface->lightmapinfo->samples)
8444                         {
8445                                 for (j = 0;j < surfacenumvertices;j++)
8446                                 {
8447                                         lm = surface->lightmapinfo->samples + offsets[j];
8448                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8449                                         VectorScale(lm, scale, c);
8450                                         if (surface->lightmapinfo->styles[1] != 255)
8451                                         {
8452                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8453                                                 lm += size3;
8454                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8455                                                 VectorMA(c, scale, lm, c);
8456                                                 if (surface->lightmapinfo->styles[2] != 255)
8457                                                 {
8458                                                         lm += size3;
8459                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8460                                                         VectorMA(c, scale, lm, c);
8461                                                         if (surface->lightmapinfo->styles[3] != 255)
8462                                                         {
8463                                                                 lm += size3;
8464                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8465                                                                 VectorMA(c, scale, lm, c);
8466                                                         }
8467                                                 }
8468                                         }
8469                                         c[0] >>= 7;
8470                                         c[1] >>= 7;
8471                                         c[2] >>= 7;
8472                                         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);
8473                                         numvertices++;
8474                                 }
8475                         }
8476                         else
8477                         {
8478                                 for (j = 0;j < surfacenumvertices;j++)
8479                                 {
8480                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8481                                         numvertices++;
8482                                 }
8483                         }
8484                 }
8485         }
8486
8487         // if vertices are deformed (sprite flares and things in maps, possibly
8488         // water waves, bulges and other deformations), modify the copied vertices
8489         // in place
8490         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8491         {
8492                 switch (deform->deform)
8493                 {
8494                 default:
8495                 case Q3DEFORM_PROJECTIONSHADOW:
8496                 case Q3DEFORM_TEXT0:
8497                 case Q3DEFORM_TEXT1:
8498                 case Q3DEFORM_TEXT2:
8499                 case Q3DEFORM_TEXT3:
8500                 case Q3DEFORM_TEXT4:
8501                 case Q3DEFORM_TEXT5:
8502                 case Q3DEFORM_TEXT6:
8503                 case Q3DEFORM_TEXT7:
8504                 case Q3DEFORM_NONE:
8505                         break;
8506                 case Q3DEFORM_AUTOSPRITE:
8507                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8508                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8509                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8510                         VectorNormalize(newforward);
8511                         VectorNormalize(newright);
8512                         VectorNormalize(newup);
8513 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8514 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8515 //                      rsurface.batchvertex3f_bufferoffset = 0;
8516 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8517 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8518 //                      rsurface.batchsvector3f_bufferoffset = 0;
8519 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8520 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8521 //                      rsurface.batchtvector3f_bufferoffset = 0;
8522 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8523 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8524 //                      rsurface.batchnormal3f_bufferoffset = 0;
8525                         // a single autosprite surface can contain multiple sprites...
8526                         for (j = 0;j < batchnumvertices - 3;j += 4)
8527                         {
8528                                 VectorClear(center);
8529                                 for (i = 0;i < 4;i++)
8530                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8531                                 VectorScale(center, 0.25f, center);
8532                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8533                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8534                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8535                                 for (i = 0;i < 4;i++)
8536                                 {
8537                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8538                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8539                                 }
8540                         }
8541                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8542                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8543                         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);
8544                         break;
8545                 case Q3DEFORM_AUTOSPRITE2:
8546                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8547                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8548                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8549                         VectorNormalize(newforward);
8550                         VectorNormalize(newright);
8551                         VectorNormalize(newup);
8552 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8553 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8554 //                      rsurface.batchvertex3f_bufferoffset = 0;
8555                         {
8556                                 const float *v1, *v2;
8557                                 vec3_t start, end;
8558                                 float f, l;
8559                                 struct
8560                                 {
8561                                         float length2;
8562                                         const float *v1;
8563                                         const float *v2;
8564                                 }
8565                                 shortest[2];
8566                                 memset(shortest, 0, sizeof(shortest));
8567                                 // a single autosprite surface can contain multiple sprites...
8568                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8569                                 {
8570                                         VectorClear(center);
8571                                         for (i = 0;i < 4;i++)
8572                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8573                                         VectorScale(center, 0.25f, center);
8574                                         // find the two shortest edges, then use them to define the
8575                                         // axis vectors for rotating around the central axis
8576                                         for (i = 0;i < 6;i++)
8577                                         {
8578                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8579                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8580                                                 l = VectorDistance2(v1, v2);
8581                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8582                                                 if (v1[2] != v2[2])
8583                                                         l += (1.0f / 1024.0f);
8584                                                 if (shortest[0].length2 > l || i == 0)
8585                                                 {
8586                                                         shortest[1] = shortest[0];
8587                                                         shortest[0].length2 = l;
8588                                                         shortest[0].v1 = v1;
8589                                                         shortest[0].v2 = v2;
8590                                                 }
8591                                                 else if (shortest[1].length2 > l || i == 1)
8592                                                 {
8593                                                         shortest[1].length2 = l;
8594                                                         shortest[1].v1 = v1;
8595                                                         shortest[1].v2 = v2;
8596                                                 }
8597                                         }
8598                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8599                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8600                                         // this calculates the right vector from the shortest edge
8601                                         // and the up vector from the edge midpoints
8602                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8603                                         VectorNormalize(right);
8604                                         VectorSubtract(end, start, up);
8605                                         VectorNormalize(up);
8606                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8607                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8608                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8609                                         VectorNegate(forward, forward);
8610                                         VectorReflect(forward, 0, up, forward);
8611                                         VectorNormalize(forward);
8612                                         CrossProduct(up, forward, newright);
8613                                         VectorNormalize(newright);
8614                                         // rotate the quad around the up axis vector, this is made
8615                                         // especially easy by the fact we know the quad is flat,
8616                                         // so we only have to subtract the center position and
8617                                         // measure distance along the right vector, and then
8618                                         // multiply that by the newright vector and add back the
8619                                         // center position
8620                                         // we also need to subtract the old position to undo the
8621                                         // displacement from the center, which we do with a
8622                                         // DotProduct, the subtraction/addition of center is also
8623                                         // optimized into DotProducts here
8624                                         l = DotProduct(right, center);
8625                                         for (i = 0;i < 4;i++)
8626                                         {
8627                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8628                                                 f = DotProduct(right, v1) - l;
8629                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8630                                         }
8631                                 }
8632                         }
8633                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8634                         {
8635 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8636 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8637 //                              rsurface.batchnormal3f_bufferoffset = 0;
8638                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8639                         }
8640                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8641                         {
8642 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8643 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8644 //                              rsurface.batchsvector3f_bufferoffset = 0;
8645 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8646 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8647 //                              rsurface.batchtvector3f_bufferoffset = 0;
8648                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8649                         }
8650                         break;
8651                 case Q3DEFORM_NORMAL:
8652                         // deform the normals to make reflections wavey
8653                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8654                         rsurface.batchnormal3f_vertexbuffer = NULL;
8655                         rsurface.batchnormal3f_bufferoffset = 0;
8656                         for (j = 0;j < batchnumvertices;j++)
8657                         {
8658                                 float vertex[3];
8659                                 float *normal = rsurface.batchnormal3f + 3*j;
8660                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8661                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8662                                 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]);
8663                                 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]);
8664                                 VectorNormalize(normal);
8665                         }
8666                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8667                         {
8668 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8669 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8670 //                              rsurface.batchsvector3f_bufferoffset = 0;
8671 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8672 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8673 //                              rsurface.batchtvector3f_bufferoffset = 0;
8674                                 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);
8675                         }
8676                         break;
8677                 case Q3DEFORM_WAVE:
8678                         // deform vertex array to make wavey water and flags and such
8679                         waveparms[0] = deform->waveparms[0];
8680                         waveparms[1] = deform->waveparms[1];
8681                         waveparms[2] = deform->waveparms[2];
8682                         waveparms[3] = deform->waveparms[3];
8683                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8684                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8685                         // this is how a divisor of vertex influence on deformation
8686                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8687                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8688 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8689 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8690 //                      rsurface.batchvertex3f_bufferoffset = 0;
8691 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8692 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8693 //                      rsurface.batchnormal3f_bufferoffset = 0;
8694                         for (j = 0;j < batchnumvertices;j++)
8695                         {
8696                                 // if the wavefunc depends on time, evaluate it per-vertex
8697                                 if (waveparms[3])
8698                                 {
8699                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8700                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8701                                 }
8702                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8703                         }
8704                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8705                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8706                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8707                         {
8708 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8709 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8710 //                              rsurface.batchsvector3f_bufferoffset = 0;
8711 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8712 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8713 //                              rsurface.batchtvector3f_bufferoffset = 0;
8714                                 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);
8715                         }
8716                         break;
8717                 case Q3DEFORM_BULGE:
8718                         // deform vertex array to make the surface have moving bulges
8719 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8720 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8721 //                      rsurface.batchvertex3f_bufferoffset = 0;
8722 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8723 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8724 //                      rsurface.batchnormal3f_bufferoffset = 0;
8725                         for (j = 0;j < batchnumvertices;j++)
8726                         {
8727                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8728                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8729                         }
8730                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8731                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8732                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8733                         {
8734 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8735 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8736 //                              rsurface.batchsvector3f_bufferoffset = 0;
8737 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8738 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8739 //                              rsurface.batchtvector3f_bufferoffset = 0;
8740                                 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);
8741                         }
8742                         break;
8743                 case Q3DEFORM_MOVE:
8744                         // deform vertex array
8745                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8746                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8747                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8748                         VectorScale(deform->parms, scale, waveparms);
8749 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8750 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8751 //                      rsurface.batchvertex3f_bufferoffset = 0;
8752                         for (j = 0;j < batchnumvertices;j++)
8753                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8754                         break;
8755                 }
8756         }
8757
8758         // generate texcoords based on the chosen texcoord source
8759         switch(rsurface.texture->tcgen.tcgen)
8760         {
8761         default:
8762         case Q3TCGEN_TEXTURE:
8763                 break;
8764         case Q3TCGEN_LIGHTMAP:
8765 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8766 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8767 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8768                 if (rsurface.batchtexcoordlightmap2f)
8769                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8770                 break;
8771         case Q3TCGEN_VECTOR:
8772 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8773 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8774 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8775                 for (j = 0;j < batchnumvertices;j++)
8776                 {
8777                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8778                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8779                 }
8780                 break;
8781         case Q3TCGEN_ENVIRONMENT:
8782                 // make environment reflections using a spheremap
8783                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8784                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8785                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8786                 for (j = 0;j < batchnumvertices;j++)
8787                 {
8788                         // identical to Q3A's method, but executed in worldspace so
8789                         // carried models can be shiny too
8790
8791                         float viewer[3], d, reflected[3], worldreflected[3];
8792
8793                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8794                         // VectorNormalize(viewer);
8795
8796                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8797
8798                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8799                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8800                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8801                         // note: this is proportinal to viewer, so we can normalize later
8802
8803                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8804                         VectorNormalize(worldreflected);
8805
8806                         // note: this sphere map only uses world x and z!
8807                         // so positive and negative y will LOOK THE SAME.
8808                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8809                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8810                 }
8811                 break;
8812         }
8813         // the only tcmod that needs software vertex processing is turbulent, so
8814         // check for it here and apply the changes if needed
8815         // and we only support that as the first one
8816         // (handling a mixture of turbulent and other tcmods would be problematic
8817         //  without punting it entirely to a software path)
8818         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8819         {
8820                 amplitude = rsurface.texture->tcmods[0].parms[1];
8821                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8822 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8823 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8824 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8825                 for (j = 0;j < batchnumvertices;j++)
8826                 {
8827                         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);
8828                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8829                 }
8830         }
8831
8832         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8833         {
8834                 // convert the modified arrays to vertex structs
8835 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8836 //              rsurface.batchvertexmeshbuffer = NULL;
8837                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8838                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8839                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8840                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8841                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8842                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8843                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8844                 {
8845                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8846                         {
8847                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8848                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8849                         }
8850                 }
8851                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8852                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8853                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8854                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8855                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8856                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8857                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8858                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8859                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8860         }
8861 }
8862
8863 void RSurf_DrawBatch(void)
8864 {
8865         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8866         // through the pipeline, killing it earlier in the pipeline would have
8867         // per-surface overhead rather than per-batch overhead, so it's best to
8868         // reject it here, before it hits glDraw.
8869         if (rsurface.batchnumtriangles == 0)
8870                 return;
8871 #if 0
8872         // batch debugging code
8873         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8874         {
8875                 int i;
8876                 int j;
8877                 int c;
8878                 const int *e;
8879                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8880                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8881                 {
8882                         c = e[i];
8883                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8884                         {
8885                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8886                                 {
8887                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8888                                                 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);
8889                                         break;
8890                                 }
8891                         }
8892                 }
8893         }
8894 #endif
8895         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);
8896 }
8897
8898 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8899 {
8900         // pick the closest matching water plane
8901         int planeindex, vertexindex, bestplaneindex = -1;
8902         float d, bestd;
8903         vec3_t vert;
8904         const float *v;
8905         r_waterstate_waterplane_t *p;
8906         qboolean prepared = false;
8907         bestd = 0;
8908         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8909         {
8910                 if(p->camera_entity != rsurface.texture->camera_entity)
8911                         continue;
8912                 d = 0;
8913                 if(!prepared)
8914                 {
8915                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8916                         prepared = true;
8917                         if(rsurface.batchnumvertices == 0)
8918                                 break;
8919                 }
8920                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8921                 {
8922                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8923                         d += fabs(PlaneDiff(vert, &p->plane));
8924                 }
8925                 if (bestd > d || bestplaneindex < 0)
8926                 {
8927                         bestd = d;
8928                         bestplaneindex = planeindex;
8929                 }
8930         }
8931         return bestplaneindex;
8932         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8933         // this situation though, as it might be better to render single larger
8934         // batches with useless stuff (backface culled for example) than to
8935         // render multiple smaller batches
8936 }
8937
8938 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8939 {
8940         int i;
8941         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8942         rsurface.passcolor4f_vertexbuffer = 0;
8943         rsurface.passcolor4f_bufferoffset = 0;
8944         for (i = 0;i < rsurface.batchnumvertices;i++)
8945                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8946 }
8947
8948 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8949 {
8950         int i;
8951         float f;
8952         const float *v;
8953         const float *c;
8954         float *c2;
8955         if (rsurface.passcolor4f)
8956         {
8957                 // generate color arrays
8958                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8959                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8960                 rsurface.passcolor4f_vertexbuffer = 0;
8961                 rsurface.passcolor4f_bufferoffset = 0;
8962                 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)
8963                 {
8964                         f = RSurf_FogVertex(v);
8965                         c2[0] = c[0] * f;
8966                         c2[1] = c[1] * f;
8967                         c2[2] = c[2] * f;
8968                         c2[3] = c[3];
8969                 }
8970         }
8971         else
8972         {
8973                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8974                 rsurface.passcolor4f_vertexbuffer = 0;
8975                 rsurface.passcolor4f_bufferoffset = 0;
8976                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8977                 {
8978                         f = RSurf_FogVertex(v);
8979                         c2[0] = f;
8980                         c2[1] = f;
8981                         c2[2] = f;
8982                         c2[3] = 1;
8983                 }
8984         }
8985 }
8986
8987 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8988 {
8989         int i;
8990         float f;
8991         const float *v;
8992         const float *c;
8993         float *c2;
8994         if (!rsurface.passcolor4f)
8995                 return;
8996         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8997         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8998         rsurface.passcolor4f_vertexbuffer = 0;
8999         rsurface.passcolor4f_bufferoffset = 0;
9000         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)
9001         {
9002                 f = RSurf_FogVertex(v);
9003                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9004                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9005                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9006                 c2[3] = c[3];
9007         }
9008 }
9009
9010 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9011 {
9012         int i;
9013         const float *c;
9014         float *c2;
9015         if (!rsurface.passcolor4f)
9016                 return;
9017         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9018         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9019         rsurface.passcolor4f_vertexbuffer = 0;
9020         rsurface.passcolor4f_bufferoffset = 0;
9021         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9022         {
9023                 c2[0] = c[0] * r;
9024                 c2[1] = c[1] * g;
9025                 c2[2] = c[2] * b;
9026                 c2[3] = c[3] * a;
9027         }
9028 }
9029
9030 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9031 {
9032         int i;
9033         const float *c;
9034         float *c2;
9035         if (!rsurface.passcolor4f)
9036                 return;
9037         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9038         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9039         rsurface.passcolor4f_vertexbuffer = 0;
9040         rsurface.passcolor4f_bufferoffset = 0;
9041         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9042         {
9043                 c2[0] = c[0] + r_refdef.scene.ambient;
9044                 c2[1] = c[1] + r_refdef.scene.ambient;
9045                 c2[2] = c[2] + r_refdef.scene.ambient;
9046                 c2[3] = c[3];
9047         }
9048 }
9049
9050 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9051 {
9052         // TODO: optimize
9053         rsurface.passcolor4f = NULL;
9054         rsurface.passcolor4f_vertexbuffer = 0;
9055         rsurface.passcolor4f_bufferoffset = 0;
9056         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9057         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9058         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9059         GL_Color(r, g, b, a);
9060         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9061         RSurf_DrawBatch();
9062 }
9063
9064 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9065 {
9066         // TODO: optimize applyfog && applycolor case
9067         // just apply fog if necessary, and tint the fog color array if necessary
9068         rsurface.passcolor4f = NULL;
9069         rsurface.passcolor4f_vertexbuffer = 0;
9070         rsurface.passcolor4f_bufferoffset = 0;
9071         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9072         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9073         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9074         GL_Color(r, g, b, a);
9075         RSurf_DrawBatch();
9076 }
9077
9078 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9079 {
9080         // TODO: optimize
9081         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9082         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9083         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9084         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9085         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9086         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9087         GL_Color(r, g, b, a);
9088         RSurf_DrawBatch();
9089 }
9090
9091 static void RSurf_DrawBatch_GL11_ClampColor(void)
9092 {
9093         int i;
9094         const float *c1;
9095         float *c2;
9096         if (!rsurface.passcolor4f)
9097                 return;
9098         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9099         {
9100                 c2[0] = bound(0.0f, c1[0], 1.0f);
9101                 c2[1] = bound(0.0f, c1[1], 1.0f);
9102                 c2[2] = bound(0.0f, c1[2], 1.0f);
9103                 c2[3] = bound(0.0f, c1[3], 1.0f);
9104         }
9105 }
9106
9107 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9108 {
9109         int i;
9110         float f;
9111         const float *v;
9112         const float *n;
9113         float *c;
9114         //vec3_t eyedir;
9115
9116         // fake shading
9117         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9118         rsurface.passcolor4f_vertexbuffer = 0;
9119         rsurface.passcolor4f_bufferoffset = 0;
9120         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)
9121         {
9122                 f = -DotProduct(r_refdef.view.forward, n);
9123                 f = max(0, f);
9124                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9125                 f *= r_refdef.lightmapintensity;
9126                 Vector4Set(c, f, f, f, 1);
9127         }
9128 }
9129
9130 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9131 {
9132         RSurf_DrawBatch_GL11_ApplyFakeLight();
9133         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9134         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9135         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9136         GL_Color(r, g, b, a);
9137         RSurf_DrawBatch();
9138 }
9139
9140 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9141 {
9142         int i;
9143         float f;
9144         float alpha;
9145         const float *v;
9146         const float *n;
9147         float *c;
9148         vec3_t ambientcolor;
9149         vec3_t diffusecolor;
9150         vec3_t lightdir;
9151         // TODO: optimize
9152         // model lighting
9153         VectorCopy(rsurface.modellight_lightdir, lightdir);
9154         f = 0.5f * r_refdef.lightmapintensity;
9155         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9156         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9157         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9158         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9159         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9160         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9161         alpha = *a;
9162         if (VectorLength2(diffusecolor) > 0)
9163         {
9164                 // q3-style directional shading
9165                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9166                 rsurface.passcolor4f_vertexbuffer = 0;
9167                 rsurface.passcolor4f_bufferoffset = 0;
9168                 for (i = 0, 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)
9169                 {
9170                         if ((f = DotProduct(n, lightdir)) > 0)
9171                                 VectorMA(ambientcolor, f, diffusecolor, c);
9172                         else
9173                                 VectorCopy(ambientcolor, c);
9174                         c[3] = alpha;
9175                 }
9176                 *r = 1;
9177                 *g = 1;
9178                 *b = 1;
9179                 *a = 1;
9180                 *applycolor = false;
9181         }
9182         else
9183         {
9184                 *r = ambientcolor[0];
9185                 *g = ambientcolor[1];
9186                 *b = ambientcolor[2];
9187                 rsurface.passcolor4f = NULL;
9188                 rsurface.passcolor4f_vertexbuffer = 0;
9189                 rsurface.passcolor4f_bufferoffset = 0;
9190         }
9191 }
9192
9193 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9194 {
9195         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9196         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9197         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9198         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9199         GL_Color(r, g, b, a);
9200         RSurf_DrawBatch();
9201 }
9202
9203 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9204 {
9205         int i;
9206         float f;
9207         const float *v;
9208         float *c;
9209         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9210         {
9211                 f = 1 - RSurf_FogVertex(v);
9212                 c[0] = r;
9213                 c[1] = g;
9214                 c[2] = b;
9215                 c[3] = f * a;
9216         }
9217 }
9218
9219 void RSurf_SetupDepthAndCulling(void)
9220 {
9221         // submodels are biased to avoid z-fighting with world surfaces that they
9222         // may be exactly overlapping (avoids z-fighting artifacts on certain
9223         // doors and things in Quake maps)
9224         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9225         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9226         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9227         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9228 }
9229
9230 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9231 {
9232         // transparent sky would be ridiculous
9233         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9234                 return;
9235         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9236         skyrenderlater = true;
9237         RSurf_SetupDepthAndCulling();
9238         GL_DepthMask(true);
9239         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9240         // skymasking on them, and Quake3 never did sky masking (unlike
9241         // software Quake and software Quake2), so disable the sky masking
9242         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9243         // and skymasking also looks very bad when noclipping outside the
9244         // level, so don't use it then either.
9245         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9246         {
9247                 R_Mesh_ResetTextureState();
9248                 if (skyrendermasked)
9249                 {
9250                         R_SetupShader_DepthOrShadow();
9251                         // depth-only (masking)
9252                         GL_ColorMask(0,0,0,0);
9253                         // just to make sure that braindead drivers don't draw
9254                         // anything despite that colormask...
9255                         GL_BlendFunc(GL_ZERO, GL_ONE);
9256                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9257                         if (rsurface.batchvertex3fbuffer)
9258                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9259                         else
9260                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9261                 }
9262                 else
9263                 {
9264                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9265                         // fog sky
9266                         GL_BlendFunc(GL_ONE, GL_ZERO);
9267                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9268                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9269                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9270                 }
9271                 RSurf_DrawBatch();
9272                 if (skyrendermasked)
9273                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9274         }
9275         R_Mesh_ResetTextureState();
9276         GL_Color(1, 1, 1, 1);
9277 }
9278
9279 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9280 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9281 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9282 {
9283         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9284                 return;
9285         if (prepass)
9286         {
9287                 // render screenspace normalmap to texture
9288                 GL_DepthMask(true);
9289                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9290                 RSurf_DrawBatch();
9291                 return;
9292         }
9293
9294         // bind lightmap texture
9295
9296         // water/refraction/reflection/camera surfaces have to be handled specially
9297         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9298         {
9299                 int start, end, startplaneindex;
9300                 for (start = 0;start < texturenumsurfaces;start = end)
9301                 {
9302                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9303                         if(startplaneindex < 0)
9304                         {
9305                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9306                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9307                                 end = start + 1;
9308                                 continue;
9309                         }
9310                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9311                                 ;
9312                         // now that we have a batch using the same planeindex, render it
9313                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9314                         {
9315                                 // render water or distortion background
9316                                 GL_DepthMask(true);
9317                                 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));
9318                                 RSurf_DrawBatch();
9319                                 // blend surface on top
9320                                 GL_DepthMask(false);
9321                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9322                                 RSurf_DrawBatch();
9323                         }
9324                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9325                         {
9326                                 // render surface with reflection texture as input
9327                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9328                                 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));
9329                                 RSurf_DrawBatch();
9330                         }
9331                 }
9332                 return;
9333         }
9334
9335         // render surface batch normally
9336         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9337         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9338         RSurf_DrawBatch();
9339 }
9340
9341 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9342 {
9343         // OpenGL 1.3 path - anything not completely ancient
9344         qboolean applycolor;
9345         qboolean applyfog;
9346         int layerindex;
9347         const texturelayer_t *layer;
9348         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);
9349         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9350
9351         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9352         {
9353                 vec4_t layercolor;
9354                 int layertexrgbscale;
9355                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9356                 {
9357                         if (layerindex == 0)
9358                                 GL_AlphaTest(true);
9359                         else
9360                         {
9361                                 GL_AlphaTest(false);
9362                                 GL_DepthFunc(GL_EQUAL);
9363                         }
9364                 }
9365                 GL_DepthMask(layer->depthmask && writedepth);
9366                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9367                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9368                 {
9369                         layertexrgbscale = 4;
9370                         VectorScale(layer->color, 0.25f, layercolor);
9371                 }
9372                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9373                 {
9374                         layertexrgbscale = 2;
9375                         VectorScale(layer->color, 0.5f, layercolor);
9376                 }
9377                 else
9378                 {
9379                         layertexrgbscale = 1;
9380                         VectorScale(layer->color, 1.0f, layercolor);
9381                 }
9382                 layercolor[3] = layer->color[3];
9383                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9384                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9385                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9386                 switch (layer->type)
9387                 {
9388                 case TEXTURELAYERTYPE_LITTEXTURE:
9389                         // single-pass lightmapped texture with 2x rgbscale
9390                         R_Mesh_TexBind(0, r_texture_white);
9391                         R_Mesh_TexMatrix(0, NULL);
9392                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9393                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9394                         R_Mesh_TexBind(1, layer->texture);
9395                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9396                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9397                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9398                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9399                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9400                         else if (FAKELIGHT_ENABLED)
9401                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9402                         else if (rsurface.uselightmaptexture)
9403                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9404                         else
9405                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9406                         break;
9407                 case TEXTURELAYERTYPE_TEXTURE:
9408                         // singletexture unlit texture with transparency support
9409                         R_Mesh_TexBind(0, layer->texture);
9410                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9411                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9412                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9413                         R_Mesh_TexBind(1, 0);
9414                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9415                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9416                         break;
9417                 case TEXTURELAYERTYPE_FOG:
9418                         // singletexture fogging
9419                         if (layer->texture)
9420                         {
9421                                 R_Mesh_TexBind(0, layer->texture);
9422                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9423                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9424                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9425                         }
9426                         else
9427                         {
9428                                 R_Mesh_TexBind(0, 0);
9429                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9430                         }
9431                         R_Mesh_TexBind(1, 0);
9432                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9433                         // generate a color array for the fog pass
9434                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9435                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9436                         RSurf_DrawBatch();
9437                         break;
9438                 default:
9439                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9440                 }
9441         }
9442         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9443         {
9444                 GL_DepthFunc(GL_LEQUAL);
9445                 GL_AlphaTest(false);
9446         }
9447 }
9448
9449 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9450 {
9451         // OpenGL 1.1 - crusty old voodoo path
9452         qboolean applyfog;
9453         int layerindex;
9454         const texturelayer_t *layer;
9455         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);
9456         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9457
9458         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9459         {
9460                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9461                 {
9462                         if (layerindex == 0)
9463                                 GL_AlphaTest(true);
9464                         else
9465                         {
9466                                 GL_AlphaTest(false);
9467                                 GL_DepthFunc(GL_EQUAL);
9468                         }
9469                 }
9470                 GL_DepthMask(layer->depthmask && writedepth);
9471                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9472                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9473                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9474                 switch (layer->type)
9475                 {
9476                 case TEXTURELAYERTYPE_LITTEXTURE:
9477                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9478                         {
9479                                 // two-pass lit texture with 2x rgbscale
9480                                 // first the lightmap pass
9481                                 R_Mesh_TexBind(0, r_texture_white);
9482                                 R_Mesh_TexMatrix(0, NULL);
9483                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9484                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9485                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9486                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9487                                 else if (FAKELIGHT_ENABLED)
9488                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9489                                 else if (rsurface.uselightmaptexture)
9490                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9491                                 else
9492                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9493                                 // then apply the texture to it
9494                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9495                                 R_Mesh_TexBind(0, layer->texture);
9496                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9497                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9498                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9499                                 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);
9500                         }
9501                         else
9502                         {
9503                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9504                                 R_Mesh_TexBind(0, layer->texture);
9505                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9506                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9507                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9508                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9509                                         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);
9510                                 else
9511                                         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);
9512                         }
9513                         break;
9514                 case TEXTURELAYERTYPE_TEXTURE:
9515                         // singletexture unlit texture with transparency support
9516                         R_Mesh_TexBind(0, layer->texture);
9517                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9518                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9519                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9520                         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);
9521                         break;
9522                 case TEXTURELAYERTYPE_FOG:
9523                         // singletexture fogging
9524                         if (layer->texture)
9525                         {
9526                                 R_Mesh_TexBind(0, layer->texture);
9527                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9528                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9529                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9530                         }
9531                         else
9532                         {
9533                                 R_Mesh_TexBind(0, 0);
9534                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9535                         }
9536                         // generate a color array for the fog pass
9537                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9538                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9539                         RSurf_DrawBatch();
9540                         break;
9541                 default:
9542                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9543                 }
9544         }
9545         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9546         {
9547                 GL_DepthFunc(GL_LEQUAL);
9548                 GL_AlphaTest(false);
9549         }
9550 }
9551
9552 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9553 {
9554         int vi;
9555         int j;
9556         r_vertexgeneric_t *batchvertex;
9557         float c[4];
9558
9559 //      R_Mesh_ResetTextureState();
9560         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9561
9562         if(rsurface.texture && rsurface.texture->currentskinframe)
9563         {
9564                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9565                 c[3] *= rsurface.texture->currentalpha;
9566         }
9567         else
9568         {
9569                 c[0] = 1;
9570                 c[1] = 0;
9571                 c[2] = 1;
9572                 c[3] = 1;
9573         }
9574
9575         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9576         {
9577                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9578                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9579                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9580         }
9581
9582         // brighten it up (as texture value 127 means "unlit")
9583         c[0] *= 2 * r_refdef.view.colorscale;
9584         c[1] *= 2 * r_refdef.view.colorscale;
9585         c[2] *= 2 * r_refdef.view.colorscale;
9586
9587         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9588                 c[3] *= r_wateralpha.value;
9589
9590         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9591         {
9592                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9593                 GL_DepthMask(false);
9594         }
9595         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9596         {
9597                 GL_BlendFunc(GL_ONE, GL_ONE);
9598                 GL_DepthMask(false);
9599         }
9600         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9601         {
9602                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9603                 GL_DepthMask(false);
9604         }
9605         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9606         {
9607                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9608                 GL_DepthMask(false);
9609         }
9610         else
9611         {
9612                 GL_BlendFunc(GL_ONE, GL_ZERO);
9613                 GL_DepthMask(writedepth);
9614         }
9615
9616         if (r_showsurfaces.integer == 3)
9617         {
9618                 rsurface.passcolor4f = NULL;
9619
9620                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9621                 {
9622                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9623
9624                         rsurface.passcolor4f = NULL;
9625                         rsurface.passcolor4f_vertexbuffer = 0;
9626                         rsurface.passcolor4f_bufferoffset = 0;
9627                 }
9628                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9629                 {
9630                         qboolean applycolor = true;
9631                         float one = 1.0;
9632
9633                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9634
9635                         r_refdef.lightmapintensity = 1;
9636                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9637                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9638                 }
9639                 else if (FAKELIGHT_ENABLED)
9640                 {
9641                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9642
9643                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9644                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9645                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9646                 }
9647                 else
9648                 {
9649                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9650
9651                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9652                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9653                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9654                 }
9655
9656                 if(!rsurface.passcolor4f)
9657                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9658
9659                 RSurf_DrawBatch_GL11_ApplyAmbient();
9660                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9661                 if(r_refdef.fogenabled)
9662                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9663                 RSurf_DrawBatch_GL11_ClampColor();
9664
9665                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9666                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9667                 RSurf_DrawBatch();
9668         }
9669         else if (!r_refdef.view.showdebug)
9670         {
9671                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9672                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9673                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9674                 {
9675                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9676                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9677                 }
9678                 R_Mesh_PrepareVertices_Generic_Unlock();
9679                 RSurf_DrawBatch();
9680         }
9681         else if (r_showsurfaces.integer == 4)
9682         {
9683                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9684                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9685                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9686                 {
9687                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9688                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9689                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9690                 }
9691                 R_Mesh_PrepareVertices_Generic_Unlock();
9692                 RSurf_DrawBatch();
9693         }
9694         else if (r_showsurfaces.integer == 2)
9695         {
9696                 const int *e;
9697                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9698                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9699                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9700                 {
9701                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9702                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9703                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9704                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9705                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9706                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9707                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9708                 }
9709                 R_Mesh_PrepareVertices_Generic_Unlock();
9710                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9711         }
9712         else
9713         {
9714                 int texturesurfaceindex;
9715                 int k;
9716                 const msurface_t *surface;
9717                 float surfacecolor4f[4];
9718                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9719                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9720                 vi = 0;
9721                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9722                 {
9723                         surface = texturesurfacelist[texturesurfaceindex];
9724                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9725                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9726                         for (j = 0;j < surface->num_vertices;j++)
9727                         {
9728                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9729                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9730                                 vi++;
9731                         }
9732                 }
9733                 R_Mesh_PrepareVertices_Generic_Unlock();
9734                 RSurf_DrawBatch();
9735         }
9736 }
9737
9738 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9739 {
9740         CHECKGLERROR
9741         RSurf_SetupDepthAndCulling();
9742         if (r_showsurfaces.integer)
9743         {
9744                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9745                 return;
9746         }
9747         switch (vid.renderpath)
9748         {
9749         case RENDERPATH_GL20:
9750         case RENDERPATH_D3D9:
9751         case RENDERPATH_D3D10:
9752         case RENDERPATH_D3D11:
9753         case RENDERPATH_SOFT:
9754         case RENDERPATH_GLES2:
9755                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9756                 break;
9757         case RENDERPATH_GL13:
9758                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9759                 break;
9760         case RENDERPATH_GL11:
9761                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9762                 break;
9763         }
9764         CHECKGLERROR
9765 }
9766
9767 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9768 {
9769         CHECKGLERROR
9770         RSurf_SetupDepthAndCulling();
9771         if (r_showsurfaces.integer)
9772         {
9773                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9774                 return;
9775         }
9776         switch (vid.renderpath)
9777         {
9778         case RENDERPATH_GL20:
9779         case RENDERPATH_D3D9:
9780         case RENDERPATH_D3D10:
9781         case RENDERPATH_D3D11:
9782         case RENDERPATH_SOFT:
9783         case RENDERPATH_GLES2:
9784                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9785                 break;
9786         case RENDERPATH_GL13:
9787                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9788                 break;
9789         case RENDERPATH_GL11:
9790                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9791                 break;
9792         }
9793         CHECKGLERROR
9794 }
9795
9796 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9797 {
9798         int i, j;
9799         int texturenumsurfaces, endsurface;
9800         texture_t *texture;
9801         const msurface_t *surface;
9802 #define MAXBATCH_TRANSPARENTSURFACES 256
9803         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9804
9805         // if the model is static it doesn't matter what value we give for
9806         // wantnormals and wanttangents, so this logic uses only rules applicable
9807         // to a model, knowing that they are meaningless otherwise
9808         if (ent == r_refdef.scene.worldentity)
9809                 RSurf_ActiveWorldEntity();
9810         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9811                 RSurf_ActiveModelEntity(ent, false, false, false);
9812         else
9813         {
9814                 switch (vid.renderpath)
9815                 {
9816                 case RENDERPATH_GL20:
9817                 case RENDERPATH_D3D9:
9818                 case RENDERPATH_D3D10:
9819                 case RENDERPATH_D3D11:
9820                 case RENDERPATH_SOFT:
9821                 case RENDERPATH_GLES2:
9822                         RSurf_ActiveModelEntity(ent, true, true, false);
9823                         break;
9824                 case RENDERPATH_GL13:
9825                 case RENDERPATH_GL11:
9826                         RSurf_ActiveModelEntity(ent, true, false, false);
9827                         break;
9828                 }
9829         }
9830
9831         if (r_transparentdepthmasking.integer)
9832         {
9833                 qboolean setup = false;
9834                 for (i = 0;i < numsurfaces;i = j)
9835                 {
9836                         j = i + 1;
9837                         surface = rsurface.modelsurfaces + surfacelist[i];
9838                         texture = surface->texture;
9839                         rsurface.texture = R_GetCurrentTexture(texture);
9840                         rsurface.lightmaptexture = NULL;
9841                         rsurface.deluxemaptexture = NULL;
9842                         rsurface.uselightmaptexture = false;
9843                         // scan ahead until we find a different texture
9844                         endsurface = min(i + 1024, numsurfaces);
9845                         texturenumsurfaces = 0;
9846                         texturesurfacelist[texturenumsurfaces++] = surface;
9847                         for (;j < endsurface;j++)
9848                         {
9849                                 surface = rsurface.modelsurfaces + surfacelist[j];
9850                                 if (texture != surface->texture)
9851                                         break;
9852                                 texturesurfacelist[texturenumsurfaces++] = surface;
9853                         }
9854                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9855                                 continue;
9856                         // render the range of surfaces as depth
9857                         if (!setup)
9858                         {
9859                                 setup = true;
9860                                 GL_ColorMask(0,0,0,0);
9861                                 GL_Color(1,1,1,1);
9862                                 GL_DepthTest(true);
9863                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9864                                 GL_DepthMask(true);
9865 //                              R_Mesh_ResetTextureState();
9866                                 R_SetupShader_DepthOrShadow();
9867                         }
9868                         RSurf_SetupDepthAndCulling();
9869                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9870                         if (rsurface.batchvertex3fbuffer)
9871                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9872                         else
9873                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9874                         RSurf_DrawBatch();
9875                 }
9876                 if (setup)
9877                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9878         }
9879
9880         for (i = 0;i < numsurfaces;i = j)
9881         {
9882                 j = i + 1;
9883                 surface = rsurface.modelsurfaces + surfacelist[i];
9884                 texture = surface->texture;
9885                 rsurface.texture = R_GetCurrentTexture(texture);
9886                 // scan ahead until we find a different texture
9887                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9888                 texturenumsurfaces = 0;
9889                 texturesurfacelist[texturenumsurfaces++] = surface;
9890                 if(FAKELIGHT_ENABLED)
9891                 {
9892                         rsurface.lightmaptexture = NULL;
9893                         rsurface.deluxemaptexture = NULL;
9894                         rsurface.uselightmaptexture = false;
9895                         for (;j < endsurface;j++)
9896                         {
9897                                 surface = rsurface.modelsurfaces + surfacelist[j];
9898                                 if (texture != surface->texture)
9899                                         break;
9900                                 texturesurfacelist[texturenumsurfaces++] = surface;
9901                         }
9902                 }
9903                 else
9904                 {
9905                         rsurface.lightmaptexture = surface->lightmaptexture;
9906                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9907                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9908                         for (;j < endsurface;j++)
9909                         {
9910                                 surface = rsurface.modelsurfaces + surfacelist[j];
9911                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9912                                         break;
9913                                 texturesurfacelist[texturenumsurfaces++] = surface;
9914                         }
9915                 }
9916                 // render the range of surfaces
9917                 if (ent == r_refdef.scene.worldentity)
9918                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9919                 else
9920                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9921         }
9922         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9923 }
9924
9925 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9926 {
9927         // transparent surfaces get pushed off into the transparent queue
9928         int surfacelistindex;
9929         const msurface_t *surface;
9930         vec3_t tempcenter, center;
9931         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9932         {
9933                 surface = texturesurfacelist[surfacelistindex];
9934                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9935                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9936                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9937                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9938                 if (queueentity->transparent_offset) // transparent offset
9939                 {
9940                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9941                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9942                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9943                 }
9944                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9945         }
9946 }
9947
9948 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9949 {
9950         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9951                 return;
9952         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9953                 return;
9954         RSurf_SetupDepthAndCulling();
9955         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9956         if (rsurface.batchvertex3fbuffer)
9957                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9958         else
9959                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9960         RSurf_DrawBatch();
9961 }
9962
9963 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9964 {
9965         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9966         CHECKGLERROR
9967         if (depthonly)
9968                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9969         else if (prepass)
9970         {
9971                 if (!rsurface.texture->currentnumlayers)
9972                         return;
9973                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9974                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9975                 else
9976                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9977         }
9978         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9979                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9980         else if (!rsurface.texture->currentnumlayers)
9981                 return;
9982         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9983         {
9984                 // in the deferred case, transparent surfaces were queued during prepass
9985                 if (!r_shadow_usingdeferredprepass)
9986                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9987         }
9988         else
9989         {
9990                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9991                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9992         }
9993         CHECKGLERROR
9994 }
9995
9996 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9997 {
9998         int i, j;
9999         texture_t *texture;
10000         R_FrameData_SetMark();
10001         // break the surface list down into batches by texture and use of lightmapping
10002         for (i = 0;i < numsurfaces;i = j)
10003         {
10004                 j = i + 1;
10005                 // texture is the base texture pointer, rsurface.texture is the
10006                 // current frame/skin the texture is directing us to use (for example
10007                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10008                 // use skin 1 instead)
10009                 texture = surfacelist[i]->texture;
10010                 rsurface.texture = R_GetCurrentTexture(texture);
10011                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10012                 {
10013                         // if this texture is not the kind we want, skip ahead to the next one
10014                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10015                                 ;
10016                         continue;
10017                 }
10018                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10019                 {
10020                         rsurface.lightmaptexture = NULL;
10021                         rsurface.deluxemaptexture = NULL;
10022                         rsurface.uselightmaptexture = false;
10023                         // simply scan ahead until we find a different texture or lightmap state
10024                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10025                                 ;
10026                 }
10027                 else
10028                 {
10029                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10030                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10031                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10032                         // simply scan ahead until we find a different texture or lightmap state
10033                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10034                                 ;
10035                 }
10036                 // render the range of surfaces
10037                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10038         }
10039         R_FrameData_ReturnToMark();
10040 }
10041
10042 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10043 {
10044         CHECKGLERROR
10045         if (depthonly)
10046                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10047         else if (prepass)
10048         {
10049                 if (!rsurface.texture->currentnumlayers)
10050                         return;
10051                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10052                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10053                 else
10054                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10055         }
10056         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10057                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10058         else if (!rsurface.texture->currentnumlayers)
10059                 return;
10060         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10061         {
10062                 // in the deferred case, transparent surfaces were queued during prepass
10063                 if (!r_shadow_usingdeferredprepass)
10064                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10065         }
10066         else
10067         {
10068                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10069                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10070         }
10071         CHECKGLERROR
10072 }
10073
10074 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10075 {
10076         int i, j;
10077         texture_t *texture;
10078         R_FrameData_SetMark();
10079         // break the surface list down into batches by texture and use of lightmapping
10080         for (i = 0;i < numsurfaces;i = j)
10081         {
10082                 j = i + 1;
10083                 // texture is the base texture pointer, rsurface.texture is the
10084                 // current frame/skin the texture is directing us to use (for example
10085                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10086                 // use skin 1 instead)
10087                 texture = surfacelist[i]->texture;
10088                 rsurface.texture = R_GetCurrentTexture(texture);
10089                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10090                 {
10091                         // if this texture is not the kind we want, skip ahead to the next one
10092                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10093                                 ;
10094                         continue;
10095                 }
10096                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10097                 {
10098                         rsurface.lightmaptexture = NULL;
10099                         rsurface.deluxemaptexture = NULL;
10100                         rsurface.uselightmaptexture = false;
10101                         // simply scan ahead until we find a different texture or lightmap state
10102                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10103                                 ;
10104                 }
10105                 else
10106                 {
10107                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10108                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10109                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10110                         // simply scan ahead until we find a different texture or lightmap state
10111                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10112                                 ;
10113                 }
10114                 // render the range of surfaces
10115                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10116         }
10117         R_FrameData_ReturnToMark();
10118 }
10119
10120 float locboxvertex3f[6*4*3] =
10121 {
10122         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10123         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10124         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10125         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10126         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10127         1,0,0, 0,0,0, 0,1,0, 1,1,0
10128 };
10129
10130 unsigned short locboxelements[6*2*3] =
10131 {
10132          0, 1, 2, 0, 2, 3,
10133          4, 5, 6, 4, 6, 7,
10134          8, 9,10, 8,10,11,
10135         12,13,14, 12,14,15,
10136         16,17,18, 16,18,19,
10137         20,21,22, 20,22,23
10138 };
10139
10140 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10141 {
10142         int i, j;
10143         cl_locnode_t *loc = (cl_locnode_t *)ent;
10144         vec3_t mins, size;
10145         float vertex3f[6*4*3];
10146         CHECKGLERROR
10147         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10148         GL_DepthMask(false);
10149         GL_DepthRange(0, 1);
10150         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10151         GL_DepthTest(true);
10152         GL_CullFace(GL_NONE);
10153         R_EntityMatrix(&identitymatrix);
10154
10155 //      R_Mesh_ResetTextureState();
10156
10157         i = surfacelist[0];
10158         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10159                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10160                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10161                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10162
10163         if (VectorCompare(loc->mins, loc->maxs))
10164         {
10165                 VectorSet(size, 2, 2, 2);
10166                 VectorMA(loc->mins, -0.5f, size, mins);
10167         }
10168         else
10169         {
10170                 VectorCopy(loc->mins, mins);
10171                 VectorSubtract(loc->maxs, loc->mins, size);
10172         }
10173
10174         for (i = 0;i < 6*4*3;)
10175                 for (j = 0;j < 3;j++, i++)
10176                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10177
10178         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10179         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10180         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10181 }
10182
10183 void R_DrawLocs(void)
10184 {
10185         int index;
10186         cl_locnode_t *loc, *nearestloc;
10187         vec3_t center;
10188         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10189         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10190         {
10191                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10192                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10193         }
10194 }
10195
10196 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10197 {
10198         if (decalsystem->decals)
10199                 Mem_Free(decalsystem->decals);
10200         memset(decalsystem, 0, sizeof(*decalsystem));
10201 }
10202
10203 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)
10204 {
10205         tridecal_t *decal;
10206         tridecal_t *decals;
10207         int i;
10208
10209         // expand or initialize the system
10210         if (decalsystem->maxdecals <= decalsystem->numdecals)
10211         {
10212                 decalsystem_t old = *decalsystem;
10213                 qboolean useshortelements;
10214                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10215                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10216                 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)));
10217                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10218                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10219                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10220                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10221                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10222                 if (decalsystem->numdecals)
10223                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10224                 if (old.decals)
10225                         Mem_Free(old.decals);
10226                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10227                         decalsystem->element3i[i] = i;
10228                 if (useshortelements)
10229                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10230                                 decalsystem->element3s[i] = i;
10231         }
10232
10233         // grab a decal and search for another free slot for the next one
10234         decals = decalsystem->decals;
10235         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10236         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10237                 ;
10238         decalsystem->freedecal = i;
10239         if (decalsystem->numdecals <= i)
10240                 decalsystem->numdecals = i + 1;
10241
10242         // initialize the decal
10243         decal->lived = 0;
10244         decal->triangleindex = triangleindex;
10245         decal->surfaceindex = surfaceindex;
10246         decal->decalsequence = decalsequence;
10247         decal->color4f[0][0] = c0[0];
10248         decal->color4f[0][1] = c0[1];
10249         decal->color4f[0][2] = c0[2];
10250         decal->color4f[0][3] = 1;
10251         decal->color4f[1][0] = c1[0];
10252         decal->color4f[1][1] = c1[1];
10253         decal->color4f[1][2] = c1[2];
10254         decal->color4f[1][3] = 1;
10255         decal->color4f[2][0] = c2[0];
10256         decal->color4f[2][1] = c2[1];
10257         decal->color4f[2][2] = c2[2];
10258         decal->color4f[2][3] = 1;
10259         decal->vertex3f[0][0] = v0[0];
10260         decal->vertex3f[0][1] = v0[1];
10261         decal->vertex3f[0][2] = v0[2];
10262         decal->vertex3f[1][0] = v1[0];
10263         decal->vertex3f[1][1] = v1[1];
10264         decal->vertex3f[1][2] = v1[2];
10265         decal->vertex3f[2][0] = v2[0];
10266         decal->vertex3f[2][1] = v2[1];
10267         decal->vertex3f[2][2] = v2[2];
10268         decal->texcoord2f[0][0] = t0[0];
10269         decal->texcoord2f[0][1] = t0[1];
10270         decal->texcoord2f[1][0] = t1[0];
10271         decal->texcoord2f[1][1] = t1[1];
10272         decal->texcoord2f[2][0] = t2[0];
10273         decal->texcoord2f[2][1] = t2[1];
10274 }
10275
10276 extern cvar_t cl_decals_bias;
10277 extern cvar_t cl_decals_models;
10278 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10279 // baseparms, parms, temps
10280 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)
10281 {
10282         int cornerindex;
10283         int index;
10284         float v[9][3];
10285         const float *vertex3f;
10286         const float *normal3f;
10287         int numpoints;
10288         float points[2][9][3];
10289         float temp[3];
10290         float tc[9][2];
10291         float f;
10292         float c[9][4];
10293         const int *e;
10294
10295         e = rsurface.modelelement3i + 3*triangleindex;
10296
10297         vertex3f = rsurface.modelvertex3f;
10298         normal3f = rsurface.modelnormal3f;
10299
10300         if (normal3f)
10301         {
10302                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10303                 {
10304                         index = 3*e[cornerindex];
10305                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10306                 }
10307         }
10308         else
10309         {
10310                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10311                 {
10312                         index = 3*e[cornerindex];
10313                         VectorCopy(vertex3f + index, v[cornerindex]);
10314                 }
10315         }
10316
10317         // cull backfaces
10318         //TriangleNormal(v[0], v[1], v[2], normal);
10319         //if (DotProduct(normal, localnormal) < 0.0f)
10320         //      continue;
10321         // clip by each of the box planes formed from the projection matrix
10322         // if anything survives, we emit the decal
10323         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]);
10324         if (numpoints < 3)
10325                 return;
10326         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]);
10327         if (numpoints < 3)
10328                 return;
10329         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]);
10330         if (numpoints < 3)
10331                 return;
10332         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]);
10333         if (numpoints < 3)
10334                 return;
10335         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]);
10336         if (numpoints < 3)
10337                 return;
10338         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]);
10339         if (numpoints < 3)
10340                 return;
10341         // some part of the triangle survived, so we have to accept it...
10342         if (dynamic)
10343         {
10344                 // dynamic always uses the original triangle
10345                 numpoints = 3;
10346                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10347                 {
10348                         index = 3*e[cornerindex];
10349                         VectorCopy(vertex3f + index, v[cornerindex]);
10350                 }
10351         }
10352         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10353         {
10354                 // convert vertex positions to texcoords
10355                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10356                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10357                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10358                 // calculate distance fade from the projection origin
10359                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10360                 f = bound(0.0f, f, 1.0f);
10361                 c[cornerindex][0] = r * f;
10362                 c[cornerindex][1] = g * f;
10363                 c[cornerindex][2] = b * f;
10364                 c[cornerindex][3] = 1.0f;
10365                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10366         }
10367         if (dynamic)
10368                 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);
10369         else
10370                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10371                         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);
10372 }
10373 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)
10374 {
10375         matrix4x4_t projection;
10376         decalsystem_t *decalsystem;
10377         qboolean dynamic;
10378         dp_model_t *model;
10379         const msurface_t *surface;
10380         const msurface_t *surfaces;
10381         const int *surfacelist;
10382         const texture_t *texture;
10383         int numtriangles;
10384         int numsurfacelist;
10385         int surfacelistindex;
10386         int surfaceindex;
10387         int triangleindex;
10388         float localorigin[3];
10389         float localnormal[3];
10390         float localmins[3];
10391         float localmaxs[3];
10392         float localsize;
10393         //float normal[3];
10394         float planes[6][4];
10395         float angles[3];
10396         bih_t *bih;
10397         int bih_triangles_count;
10398         int bih_triangles[256];
10399         int bih_surfaces[256];
10400
10401         decalsystem = &ent->decalsystem;
10402         model = ent->model;
10403         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10404         {
10405                 R_DecalSystem_Reset(&ent->decalsystem);
10406                 return;
10407         }
10408
10409         if (!model->brush.data_leafs && !cl_decals_models.integer)
10410         {
10411                 if (decalsystem->model)
10412                         R_DecalSystem_Reset(decalsystem);
10413                 return;
10414         }
10415
10416         if (decalsystem->model != model)
10417                 R_DecalSystem_Reset(decalsystem);
10418         decalsystem->model = model;
10419
10420         RSurf_ActiveModelEntity(ent, true, false, false);
10421
10422         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10423         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10424         VectorNormalize(localnormal);
10425         localsize = worldsize*rsurface.inversematrixscale;
10426         localmins[0] = localorigin[0] - localsize;
10427         localmins[1] = localorigin[1] - localsize;
10428         localmins[2] = localorigin[2] - localsize;
10429         localmaxs[0] = localorigin[0] + localsize;
10430         localmaxs[1] = localorigin[1] + localsize;
10431         localmaxs[2] = localorigin[2] + localsize;
10432
10433         //VectorCopy(localnormal, planes[4]);
10434         //VectorVectors(planes[4], planes[2], planes[0]);
10435         AnglesFromVectors(angles, localnormal, NULL, false);
10436         AngleVectors(angles, planes[0], planes[2], planes[4]);
10437         VectorNegate(planes[0], planes[1]);
10438         VectorNegate(planes[2], planes[3]);
10439         VectorNegate(planes[4], planes[5]);
10440         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10441         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10442         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10443         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10444         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10445         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10446
10447 #if 1
10448 // works
10449 {
10450         matrix4x4_t forwardprojection;
10451         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10452         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10453 }
10454 #else
10455 // broken
10456 {
10457         float projectionvector[4][3];
10458         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10459         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10460         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10461         projectionvector[0][0] = planes[0][0] * ilocalsize;
10462         projectionvector[0][1] = planes[1][0] * ilocalsize;
10463         projectionvector[0][2] = planes[2][0] * ilocalsize;
10464         projectionvector[1][0] = planes[0][1] * ilocalsize;
10465         projectionvector[1][1] = planes[1][1] * ilocalsize;
10466         projectionvector[1][2] = planes[2][1] * ilocalsize;
10467         projectionvector[2][0] = planes[0][2] * ilocalsize;
10468         projectionvector[2][1] = planes[1][2] * ilocalsize;
10469         projectionvector[2][2] = planes[2][2] * ilocalsize;
10470         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10471         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10472         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10473         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10474 }
10475 #endif
10476
10477         dynamic = model->surfmesh.isanimated;
10478         numsurfacelist = model->nummodelsurfaces;
10479         surfacelist = model->sortedmodelsurfaces;
10480         surfaces = model->data_surfaces;
10481
10482         bih = NULL;
10483         bih_triangles_count = -1;
10484         if(!dynamic)
10485         {
10486                 if(model->render_bih.numleafs)
10487                         bih = &model->render_bih;
10488                 else if(model->collision_bih.numleafs)
10489                         bih = &model->collision_bih;
10490         }
10491         if(bih)
10492                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10493         if(bih_triangles_count == 0)
10494                 return;
10495         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10496                 return;
10497         if(bih_triangles_count > 0)
10498         {
10499                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10500                 {
10501                         surfaceindex = bih_surfaces[triangleindex];
10502                         surface = surfaces + surfaceindex;
10503                         texture = surface->texture;
10504                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10505                                 continue;
10506                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10507                                 continue;
10508                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10509                 }
10510         }
10511         else
10512         {
10513                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10514                 {
10515                         surfaceindex = surfacelist[surfacelistindex];
10516                         surface = surfaces + surfaceindex;
10517                         // check cull box first because it rejects more than any other check
10518                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10519                                 continue;
10520                         // skip transparent surfaces
10521                         texture = surface->texture;
10522                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10523                                 continue;
10524                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10525                                 continue;
10526                         numtriangles = surface->num_triangles;
10527                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10528                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10529                 }
10530         }
10531 }
10532
10533 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10534 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)
10535 {
10536         int renderentityindex;
10537         float worldmins[3];
10538         float worldmaxs[3];
10539         entity_render_t *ent;
10540
10541         if (!cl_decals_newsystem.integer)
10542                 return;
10543
10544         worldmins[0] = worldorigin[0] - worldsize;
10545         worldmins[1] = worldorigin[1] - worldsize;
10546         worldmins[2] = worldorigin[2] - worldsize;
10547         worldmaxs[0] = worldorigin[0] + worldsize;
10548         worldmaxs[1] = worldorigin[1] + worldsize;
10549         worldmaxs[2] = worldorigin[2] + worldsize;
10550
10551         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10552
10553         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10554         {
10555                 ent = r_refdef.scene.entities[renderentityindex];
10556                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10557                         continue;
10558
10559                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10560         }
10561 }
10562
10563 typedef struct r_decalsystem_splatqueue_s
10564 {
10565         vec3_t worldorigin;
10566         vec3_t worldnormal;
10567         float color[4];
10568         float tcrange[4];
10569         float worldsize;
10570         int decalsequence;
10571 }
10572 r_decalsystem_splatqueue_t;
10573
10574 int r_decalsystem_numqueued = 0;
10575 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10576
10577 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)
10578 {
10579         r_decalsystem_splatqueue_t *queue;
10580
10581         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10582                 return;
10583
10584         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10585         VectorCopy(worldorigin, queue->worldorigin);
10586         VectorCopy(worldnormal, queue->worldnormal);
10587         Vector4Set(queue->color, r, g, b, a);
10588         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10589         queue->worldsize = worldsize;
10590         queue->decalsequence = cl.decalsequence++;
10591 }
10592
10593 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10594 {
10595         int i;
10596         r_decalsystem_splatqueue_t *queue;
10597
10598         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10599                 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);
10600         r_decalsystem_numqueued = 0;
10601 }
10602
10603 extern cvar_t cl_decals_max;
10604 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10605 {
10606         int i;
10607         decalsystem_t *decalsystem = &ent->decalsystem;
10608         int numdecals;
10609         int killsequence;
10610         tridecal_t *decal;
10611         float frametime;
10612         float lifetime;
10613
10614         if (!decalsystem->numdecals)
10615                 return;
10616
10617         if (r_showsurfaces.integer)
10618                 return;
10619
10620         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10621         {
10622                 R_DecalSystem_Reset(decalsystem);
10623                 return;
10624         }
10625
10626         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10627         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10628
10629         if (decalsystem->lastupdatetime)
10630                 frametime = (cl.time - decalsystem->lastupdatetime);
10631         else
10632                 frametime = 0;
10633         decalsystem->lastupdatetime = cl.time;
10634         decal = decalsystem->decals;
10635         numdecals = decalsystem->numdecals;
10636
10637         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10638         {
10639                 if (decal->color4f[0][3])
10640                 {
10641                         decal->lived += frametime;
10642                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10643                         {
10644                                 memset(decal, 0, sizeof(*decal));
10645                                 if (decalsystem->freedecal > i)
10646                                         decalsystem->freedecal = i;
10647                         }
10648                 }
10649         }
10650         decal = decalsystem->decals;
10651         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10652                 numdecals--;
10653
10654         // collapse the array by shuffling the tail decals into the gaps
10655         for (;;)
10656         {
10657                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10658                         decalsystem->freedecal++;
10659                 if (decalsystem->freedecal == numdecals)
10660                         break;
10661                 decal[decalsystem->freedecal] = decal[--numdecals];
10662         }
10663
10664         decalsystem->numdecals = numdecals;
10665
10666         if (numdecals <= 0)
10667         {
10668                 // if there are no decals left, reset decalsystem
10669                 R_DecalSystem_Reset(decalsystem);
10670         }
10671 }
10672
10673 extern skinframe_t *decalskinframe;
10674 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10675 {
10676         int i;
10677         decalsystem_t *decalsystem = &ent->decalsystem;
10678         int numdecals;
10679         tridecal_t *decal;
10680         float faderate;
10681         float alpha;
10682         float *v3f;
10683         float *c4f;
10684         float *t2f;
10685         const int *e;
10686         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10687         int numtris = 0;
10688
10689         numdecals = decalsystem->numdecals;
10690         if (!numdecals)
10691                 return;
10692
10693         if (r_showsurfaces.integer)
10694                 return;
10695
10696         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10697         {
10698                 R_DecalSystem_Reset(decalsystem);
10699                 return;
10700         }
10701
10702         // if the model is static it doesn't matter what value we give for
10703         // wantnormals and wanttangents, so this logic uses only rules applicable
10704         // to a model, knowing that they are meaningless otherwise
10705         if (ent == r_refdef.scene.worldentity)
10706                 RSurf_ActiveWorldEntity();
10707         else
10708                 RSurf_ActiveModelEntity(ent, false, false, false);
10709
10710         decalsystem->lastupdatetime = cl.time;
10711         decal = decalsystem->decals;
10712
10713         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10714
10715         // update vertex positions for animated models
10716         v3f = decalsystem->vertex3f;
10717         c4f = decalsystem->color4f;
10718         t2f = decalsystem->texcoord2f;
10719         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10720         {
10721                 if (!decal->color4f[0][3])
10722                         continue;
10723
10724                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10725                         continue;
10726
10727                 // update color values for fading decals
10728                 if (decal->lived >= cl_decals_time.value)
10729                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10730                 else
10731                         alpha = 1.0f;
10732
10733                 c4f[ 0] = decal->color4f[0][0] * alpha;
10734                 c4f[ 1] = decal->color4f[0][1] * alpha;
10735                 c4f[ 2] = decal->color4f[0][2] * alpha;
10736                 c4f[ 3] = 1;
10737                 c4f[ 4] = decal->color4f[1][0] * alpha;
10738                 c4f[ 5] = decal->color4f[1][1] * alpha;
10739                 c4f[ 6] = decal->color4f[1][2] * alpha;
10740                 c4f[ 7] = 1;
10741                 c4f[ 8] = decal->color4f[2][0] * alpha;
10742                 c4f[ 9] = decal->color4f[2][1] * alpha;
10743                 c4f[10] = decal->color4f[2][2] * alpha;
10744                 c4f[11] = 1;
10745
10746                 t2f[0] = decal->texcoord2f[0][0];
10747                 t2f[1] = decal->texcoord2f[0][1];
10748                 t2f[2] = decal->texcoord2f[1][0];
10749                 t2f[3] = decal->texcoord2f[1][1];
10750                 t2f[4] = decal->texcoord2f[2][0];
10751                 t2f[5] = decal->texcoord2f[2][1];
10752
10753                 // update vertex positions for animated models
10754                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10755                 {
10756                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10757                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10758                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10759                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10760                 }
10761                 else
10762                 {
10763                         VectorCopy(decal->vertex3f[0], v3f);
10764                         VectorCopy(decal->vertex3f[1], v3f + 3);
10765                         VectorCopy(decal->vertex3f[2], v3f + 6);
10766                 }
10767
10768                 if (r_refdef.fogenabled)
10769                 {
10770                         alpha = RSurf_FogVertex(v3f);
10771                         VectorScale(c4f, alpha, c4f);
10772                         alpha = RSurf_FogVertex(v3f + 3);
10773                         VectorScale(c4f + 4, alpha, c4f + 4);
10774                         alpha = RSurf_FogVertex(v3f + 6);
10775                         VectorScale(c4f + 8, alpha, c4f + 8);
10776                 }
10777
10778                 v3f += 9;
10779                 c4f += 12;
10780                 t2f += 6;
10781                 numtris++;
10782         }
10783
10784         if (numtris > 0)
10785         {
10786                 r_refdef.stats.drawndecals += numtris;
10787
10788                 // now render the decals all at once
10789                 // (this assumes they all use one particle font texture!)
10790                 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);
10791 //              R_Mesh_ResetTextureState();
10792                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10793                 GL_DepthMask(false);
10794                 GL_DepthRange(0, 1);
10795                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10796                 GL_DepthTest(true);
10797                 GL_CullFace(GL_NONE);
10798                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10799                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10800                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10801         }
10802 }
10803
10804 static void R_DrawModelDecals(void)
10805 {
10806         int i, numdecals;
10807
10808         // fade faster when there are too many decals
10809         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10810         for (i = 0;i < r_refdef.scene.numentities;i++)
10811                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10812
10813         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10814         for (i = 0;i < r_refdef.scene.numentities;i++)
10815                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10816                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10817
10818         R_DecalSystem_ApplySplatEntitiesQueue();
10819
10820         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10821         for (i = 0;i < r_refdef.scene.numentities;i++)
10822                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10823
10824         r_refdef.stats.totaldecals += numdecals;
10825
10826         if (r_showsurfaces.integer)
10827                 return;
10828
10829         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10830
10831         for (i = 0;i < r_refdef.scene.numentities;i++)
10832         {
10833                 if (!r_refdef.viewcache.entityvisible[i])
10834                         continue;
10835                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10836                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10837         }
10838 }
10839
10840 extern cvar_t mod_collision_bih;
10841 void R_DrawDebugModel(void)
10842 {
10843         entity_render_t *ent = rsurface.entity;
10844         int i, j, k, l, flagsmask;
10845         const msurface_t *surface;
10846         dp_model_t *model = ent->model;
10847         vec3_t v;
10848
10849         switch(vid.renderpath)
10850         {
10851         case RENDERPATH_GL11:
10852         case RENDERPATH_GL13:
10853         case RENDERPATH_GL20:
10854                 break;
10855         case RENDERPATH_D3D9:
10856                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10857                 return;
10858         case RENDERPATH_D3D10:
10859                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10860                 return;
10861         case RENDERPATH_D3D11:
10862                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10863                 return;
10864         case RENDERPATH_SOFT:
10865                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10866                 return;
10867         case RENDERPATH_GLES2:
10868                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10869                 return;
10870         }
10871
10872         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10873
10874 //      R_Mesh_ResetTextureState();
10875         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10876         GL_DepthRange(0, 1);
10877         GL_DepthTest(!r_showdisabledepthtest.integer);
10878         GL_DepthMask(false);
10879         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10880
10881         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10882         {
10883                 int triangleindex;
10884                 int bihleafindex;
10885                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10886                 const q3mbrush_t *brush;
10887                 const bih_t *bih = &model->collision_bih;
10888                 const bih_leaf_t *bihleaf;
10889                 float vertex3f[3][3];
10890                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10891                 cullbox = false;
10892                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10893                 {
10894                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10895                                 continue;
10896                         switch (bihleaf->type)
10897                         {
10898                         case BIH_BRUSH:
10899                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10900                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10901                                 {
10902                                         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);
10903                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10904                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10905                                 }
10906                                 break;
10907                         case BIH_COLLISIONTRIANGLE:
10908                                 triangleindex = bihleaf->itemindex;
10909                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10910                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10911                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10912                                 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);
10913                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10914                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10915                                 break;
10916                         case BIH_RENDERTRIANGLE:
10917                                 triangleindex = bihleaf->itemindex;
10918                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10919                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10920                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10921                                 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);
10922                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10923                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10924                                 break;
10925                         }
10926                 }
10927         }
10928
10929         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10930
10931         if (r_showtris.integer || (r_shownormals.value != 0))
10932         {
10933                 if (r_showdisabledepthtest.integer)
10934                 {
10935                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10936                         GL_DepthMask(false);
10937                 }
10938                 else
10939                 {
10940                         GL_BlendFunc(GL_ONE, GL_ZERO);
10941                         GL_DepthMask(true);
10942                 }
10943                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10944                 {
10945                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10946                                 continue;
10947                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10948                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10949                         {
10950                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10951                                 if (r_showtris.value > 0)
10952                                 {
10953                                         if (!rsurface.texture->currentlayers->depthmask)
10954                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10955                                         else if (ent == r_refdef.scene.worldentity)
10956                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10957                                         else
10958                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10959                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10960                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10961                                         RSurf_DrawBatch();
10962                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10963                                         CHECKGLERROR
10964                                 }
10965                                 if (r_shownormals.value < 0)
10966                                 {
10967                                         qglBegin(GL_LINES);
10968                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10969                                         {
10970                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10971                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10972                                                 qglVertex3f(v[0], v[1], v[2]);
10973                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10974                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10975                                                 qglVertex3f(v[0], v[1], v[2]);
10976                                         }
10977                                         qglEnd();
10978                                         CHECKGLERROR
10979                                 }
10980                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10981                                 {
10982                                         qglBegin(GL_LINES);
10983                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10984                                         {
10985                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10986                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10987                                                 qglVertex3f(v[0], v[1], v[2]);
10988                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10989                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10990                                                 qglVertex3f(v[0], v[1], v[2]);
10991                                         }
10992                                         qglEnd();
10993                                         CHECKGLERROR
10994                                         qglBegin(GL_LINES);
10995                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10996                                         {
10997                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10998                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10999                                                 qglVertex3f(v[0], v[1], v[2]);
11000                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11001                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11002                                                 qglVertex3f(v[0], v[1], v[2]);
11003                                         }
11004                                         qglEnd();
11005                                         CHECKGLERROR
11006                                         qglBegin(GL_LINES);
11007                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11008                                         {
11009                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11010                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11011                                                 qglVertex3f(v[0], v[1], v[2]);
11012                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11013                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11014                                                 qglVertex3f(v[0], v[1], v[2]);
11015                                         }
11016                                         qglEnd();
11017                                         CHECKGLERROR
11018                                 }
11019                         }
11020                 }
11021                 rsurface.texture = NULL;
11022         }
11023 }
11024
11025 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11026 int r_maxsurfacelist = 0;
11027 const msurface_t **r_surfacelist = NULL;
11028 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11029 {
11030         int i, j, endj, flagsmask;
11031         dp_model_t *model = r_refdef.scene.worldmodel;
11032         msurface_t *surfaces;
11033         unsigned char *update;
11034         int numsurfacelist = 0;
11035         if (model == NULL)
11036                 return;
11037
11038         if (r_maxsurfacelist < model->num_surfaces)
11039         {
11040                 r_maxsurfacelist = model->num_surfaces;
11041                 if (r_surfacelist)
11042                         Mem_Free((msurface_t**)r_surfacelist);
11043                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11044         }
11045
11046         RSurf_ActiveWorldEntity();
11047
11048         surfaces = model->data_surfaces;
11049         update = model->brushq1.lightmapupdateflags;
11050
11051         // update light styles on this submodel
11052         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11053         {
11054                 model_brush_lightstyleinfo_t *style;
11055                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11056                 {
11057                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11058                         {
11059                                 int *list = style->surfacelist;
11060                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11061                                 for (j = 0;j < style->numsurfaces;j++)
11062                                         update[list[j]] = true;
11063                         }
11064                 }
11065         }
11066
11067         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11068
11069         if (debug)
11070         {
11071                 R_DrawDebugModel();
11072                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11073                 return;
11074         }
11075
11076         rsurface.lightmaptexture = NULL;
11077         rsurface.deluxemaptexture = NULL;
11078         rsurface.uselightmaptexture = false;
11079         rsurface.texture = NULL;
11080         rsurface.rtlight = NULL;
11081         numsurfacelist = 0;
11082         // add visible surfaces to draw list
11083         for (i = 0;i < model->nummodelsurfaces;i++)
11084         {
11085                 j = model->sortedmodelsurfaces[i];
11086                 if (r_refdef.viewcache.world_surfacevisible[j])
11087                         r_surfacelist[numsurfacelist++] = surfaces + j;
11088         }
11089         // update lightmaps if needed
11090         if (model->brushq1.firstrender)
11091         {
11092                 model->brushq1.firstrender = false;
11093                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11094                         if (update[j])
11095                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11096         }
11097         else if (update)
11098         {
11099                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11100                         if (r_refdef.viewcache.world_surfacevisible[j])
11101                                 if (update[j])
11102                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11103         }
11104         // don't do anything if there were no surfaces
11105         if (!numsurfacelist)
11106         {
11107                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11108                 return;
11109         }
11110         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11111
11112         // add to stats if desired
11113         if (r_speeds.integer && !skysurfaces && !depthonly)
11114         {
11115                 r_refdef.stats.world_surfaces += numsurfacelist;
11116                 for (j = 0;j < numsurfacelist;j++)
11117                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11118         }
11119
11120         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11121 }
11122
11123 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11124 {
11125         int i, j, endj, flagsmask;
11126         dp_model_t *model = ent->model;
11127         msurface_t *surfaces;
11128         unsigned char *update;
11129         int numsurfacelist = 0;
11130         if (model == NULL)
11131                 return;
11132
11133         if (r_maxsurfacelist < model->num_surfaces)
11134         {
11135                 r_maxsurfacelist = model->num_surfaces;
11136                 if (r_surfacelist)
11137                         Mem_Free((msurface_t **)r_surfacelist);
11138                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11139         }
11140
11141         // if the model is static it doesn't matter what value we give for
11142         // wantnormals and wanttangents, so this logic uses only rules applicable
11143         // to a model, knowing that they are meaningless otherwise
11144         if (ent == r_refdef.scene.worldentity)
11145                 RSurf_ActiveWorldEntity();
11146         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11147                 RSurf_ActiveModelEntity(ent, false, false, false);
11148         else if (prepass)
11149                 RSurf_ActiveModelEntity(ent, true, true, true);
11150         else if (depthonly)
11151         {
11152                 switch (vid.renderpath)
11153                 {
11154                 case RENDERPATH_GL20:
11155                 case RENDERPATH_D3D9:
11156                 case RENDERPATH_D3D10:
11157                 case RENDERPATH_D3D11:
11158                 case RENDERPATH_SOFT:
11159                 case RENDERPATH_GLES2:
11160                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11161                         break;
11162                 case RENDERPATH_GL13:
11163                 case RENDERPATH_GL11:
11164                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11165                         break;
11166                 }
11167         }
11168         else
11169         {
11170                 switch (vid.renderpath)
11171                 {
11172                 case RENDERPATH_GL20:
11173                 case RENDERPATH_D3D9:
11174                 case RENDERPATH_D3D10:
11175                 case RENDERPATH_D3D11:
11176                 case RENDERPATH_SOFT:
11177                 case RENDERPATH_GLES2:
11178                         RSurf_ActiveModelEntity(ent, true, true, false);
11179                         break;
11180                 case RENDERPATH_GL13:
11181                 case RENDERPATH_GL11:
11182                         RSurf_ActiveModelEntity(ent, true, false, false);
11183                         break;
11184                 }
11185         }
11186
11187         surfaces = model->data_surfaces;
11188         update = model->brushq1.lightmapupdateflags;
11189
11190         // update light styles
11191         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11192         {
11193                 model_brush_lightstyleinfo_t *style;
11194                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11195                 {
11196                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11197                         {
11198                                 int *list = style->surfacelist;
11199                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11200                                 for (j = 0;j < style->numsurfaces;j++)
11201                                         update[list[j]] = true;
11202                         }
11203                 }
11204         }
11205
11206         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11207
11208         if (debug)
11209         {
11210                 R_DrawDebugModel();
11211                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11212                 return;
11213         }
11214
11215         rsurface.lightmaptexture = NULL;
11216         rsurface.deluxemaptexture = NULL;
11217         rsurface.uselightmaptexture = false;
11218         rsurface.texture = NULL;
11219         rsurface.rtlight = NULL;
11220         numsurfacelist = 0;
11221         // add visible surfaces to draw list
11222         for (i = 0;i < model->nummodelsurfaces;i++)
11223                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11224         // don't do anything if there were no surfaces
11225         if (!numsurfacelist)
11226         {
11227                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11228                 return;
11229         }
11230         // update lightmaps if needed
11231         if (update)
11232         {
11233                 int updated = 0;
11234                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11235                 {
11236                         if (update[j])
11237                         {
11238                                 updated++;
11239                                 R_BuildLightMap(ent, surfaces + j);
11240                         }
11241                 }
11242         }
11243         if (update)
11244                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11245                         if (update[j])
11246                                 R_BuildLightMap(ent, surfaces + j);
11247         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11248
11249         // add to stats if desired
11250         if (r_speeds.integer && !skysurfaces && !depthonly)
11251         {
11252                 r_refdef.stats.entities_surfaces += numsurfacelist;
11253                 for (j = 0;j < numsurfacelist;j++)
11254                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11255         }
11256
11257         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11258 }
11259
11260 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11261 {
11262         static texture_t texture;
11263         static msurface_t surface;
11264         const msurface_t *surfacelist = &surface;
11265
11266         // fake enough texture and surface state to render this geometry
11267
11268         texture.update_lastrenderframe = -1; // regenerate this texture
11269         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11270         texture.currentskinframe = skinframe;
11271         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11272         texture.offsetmapping = OFFSETMAPPING_OFF;
11273         texture.offsetscale = 1;
11274         texture.specularscalemod = 1;
11275         texture.specularpowermod = 1;
11276
11277         surface.texture = &texture;
11278         surface.num_triangles = numtriangles;
11279         surface.num_firsttriangle = firsttriangle;
11280         surface.num_vertices = numvertices;
11281         surface.num_firstvertex = firstvertex;
11282
11283         // now render it
11284         rsurface.texture = R_GetCurrentTexture(surface.texture);
11285         rsurface.lightmaptexture = NULL;
11286         rsurface.deluxemaptexture = NULL;
11287         rsurface.uselightmaptexture = false;
11288         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11289 }
11290
11291 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)
11292 {
11293         static msurface_t surface;
11294         const msurface_t *surfacelist = &surface;
11295
11296         // fake enough texture and surface state to render this geometry
11297         surface.texture = texture;
11298         surface.num_triangles = numtriangles;
11299         surface.num_firsttriangle = firsttriangle;
11300         surface.num_vertices = numvertices;
11301         surface.num_firstvertex = firstvertex;
11302
11303         // now render it
11304         rsurface.texture = R_GetCurrentTexture(surface.texture);
11305         rsurface.lightmaptexture = NULL;
11306         rsurface.deluxemaptexture = NULL;
11307         rsurface.uselightmaptexture = false;
11308         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11309 }