]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
new con_closeontoggleconsole logic:
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
120
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129
130 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
131 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
132
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
146 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
147 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
148 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
149 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
150 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
156 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
157 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
158
159 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
160 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
161 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
162 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
163 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
164 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
165
166 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
167 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
168 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
169 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
170
171 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
172 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
173 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
174 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
175 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
176 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
177 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
178
179 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
180 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
181 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
182 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
183 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
184 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
185 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
186 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
187 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
188 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
189
190 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
191
192 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
193
194 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
195
196 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
197 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
198 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
199 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
200 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
201 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
202 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
203 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
204 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
205
206 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
207 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
208
209 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
210
211 extern cvar_t v_glslgamma;
212
213 extern qboolean v_flipped_state;
214
215 static struct r_bloomstate_s
216 {
217         qboolean enabled;
218         qboolean hdr;
219
220         int bloomwidth, bloomheight;
221
222         int screentexturewidth, screentextureheight;
223         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
224
225         int bloomtexturewidth, bloomtextureheight;
226         rtexture_t *texture_bloom;
227
228         // arrays for rendering the screen passes
229         float screentexcoord2f[8];
230         float bloomtexcoord2f[8];
231         float offsettexcoord2f[8];
232
233         r_viewport_t viewport;
234 }
235 r_bloomstate;
236
237 r_waterstate_t r_waterstate;
238
239 /// shadow volume bsp struct with automatically growing nodes buffer
240 svbsp_t r_svbsp;
241
242 rtexture_t *r_texture_blanknormalmap;
243 rtexture_t *r_texture_white;
244 rtexture_t *r_texture_grey128;
245 rtexture_t *r_texture_black;
246 rtexture_t *r_texture_notexture;
247 rtexture_t *r_texture_whitecube;
248 rtexture_t *r_texture_normalizationcube;
249 rtexture_t *r_texture_fogattenuation;
250 rtexture_t *r_texture_fogheighttexture;
251 rtexture_t *r_texture_gammaramps;
252 unsigned int r_texture_gammaramps_serial;
253 //rtexture_t *r_texture_fogintensity;
254 rtexture_t *r_texture_reflectcube;
255
256 // TODO: hash lookups?
257 typedef struct cubemapinfo_s
258 {
259         char basename[64];
260         rtexture_t *texture;
261 }
262 cubemapinfo_t;
263
264 int r_texture_numcubemaps;
265 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
266
267 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
268 unsigned int r_numqueries;
269 unsigned int r_maxqueries;
270
271 typedef struct r_qwskincache_s
272 {
273         char name[MAX_QPATH];
274         skinframe_t *skinframe;
275 }
276 r_qwskincache_t;
277
278 static r_qwskincache_t *r_qwskincache;
279 static int r_qwskincache_size;
280
281 /// vertex coordinates for a quad that covers the screen exactly
282 extern const float r_screenvertex3f[12];
283 extern const float r_d3dscreenvertex3f[12];
284 const float r_screenvertex3f[12] =
285 {
286         0, 0, 0,
287         1, 0, 0,
288         1, 1, 0,
289         0, 1, 0
290 };
291 const float r_d3dscreenvertex3f[12] =
292 {
293         0, 1, 0,
294         1, 1, 0,
295         1, 0, 0,
296         0, 0, 0
297 };
298
299 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
300 {
301         int i;
302         for (i = 0;i < verts;i++)
303         {
304                 out[0] = in[0] * r;
305                 out[1] = in[1] * g;
306                 out[2] = in[2] * b;
307                 out[3] = in[3];
308                 in += 4;
309                 out += 4;
310         }
311 }
312
313 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
314 {
315         int i;
316         for (i = 0;i < verts;i++)
317         {
318                 out[0] = r;
319                 out[1] = g;
320                 out[2] = b;
321                 out[3] = a;
322                 out += 4;
323         }
324 }
325
326 // FIXME: move this to client?
327 void FOG_clear(void)
328 {
329         if (gamemode == GAME_NEHAHRA)
330         {
331                 Cvar_Set("gl_fogenable", "0");
332                 Cvar_Set("gl_fogdensity", "0.2");
333                 Cvar_Set("gl_fogred", "0.3");
334                 Cvar_Set("gl_foggreen", "0.3");
335                 Cvar_Set("gl_fogblue", "0.3");
336         }
337         r_refdef.fog_density = 0;
338         r_refdef.fog_red = 0;
339         r_refdef.fog_green = 0;
340         r_refdef.fog_blue = 0;
341         r_refdef.fog_alpha = 1;
342         r_refdef.fog_start = 0;
343         r_refdef.fog_end = 16384;
344         r_refdef.fog_height = 1<<30;
345         r_refdef.fog_fadedepth = 128;
346         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
347 }
348
349 static void R_BuildBlankTextures(void)
350 {
351         unsigned char data[4];
352         data[2] = 128; // normal X
353         data[1] = 128; // normal Y
354         data[0] = 255; // normal Z
355         data[3] = 128; // height
356         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
357         data[0] = 255;
358         data[1] = 255;
359         data[2] = 255;
360         data[3] = 255;
361         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
362         data[0] = 128;
363         data[1] = 128;
364         data[2] = 128;
365         data[3] = 255;
366         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
367         data[0] = 0;
368         data[1] = 0;
369         data[2] = 0;
370         data[3] = 255;
371         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
372 }
373
374 static void R_BuildNoTexture(void)
375 {
376         int x, y;
377         unsigned char pix[16][16][4];
378         // this makes a light grey/dark grey checkerboard texture
379         for (y = 0;y < 16;y++)
380         {
381                 for (x = 0;x < 16;x++)
382                 {
383                         if ((y < 8) ^ (x < 8))
384                         {
385                                 pix[y][x][0] = 128;
386                                 pix[y][x][1] = 128;
387                                 pix[y][x][2] = 128;
388                                 pix[y][x][3] = 255;
389                         }
390                         else
391                         {
392                                 pix[y][x][0] = 64;
393                                 pix[y][x][1] = 64;
394                                 pix[y][x][2] = 64;
395                                 pix[y][x][3] = 255;
396                         }
397                 }
398         }
399         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
400 }
401
402 static void R_BuildWhiteCube(void)
403 {
404         unsigned char data[6*1*1*4];
405         memset(data, 255, sizeof(data));
406         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
407 }
408
409 static void R_BuildNormalizationCube(void)
410 {
411         int x, y, side;
412         vec3_t v;
413         vec_t s, t, intensity;
414 #define NORMSIZE 64
415         unsigned char *data;
416         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
417         for (side = 0;side < 6;side++)
418         {
419                 for (y = 0;y < NORMSIZE;y++)
420                 {
421                         for (x = 0;x < NORMSIZE;x++)
422                         {
423                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
424                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
425                                 switch(side)
426                                 {
427                                 default:
428                                 case 0:
429                                         v[0] = 1;
430                                         v[1] = -t;
431                                         v[2] = -s;
432                                         break;
433                                 case 1:
434                                         v[0] = -1;
435                                         v[1] = -t;
436                                         v[2] = s;
437                                         break;
438                                 case 2:
439                                         v[0] = s;
440                                         v[1] = 1;
441                                         v[2] = t;
442                                         break;
443                                 case 3:
444                                         v[0] = s;
445                                         v[1] = -1;
446                                         v[2] = -t;
447                                         break;
448                                 case 4:
449                                         v[0] = s;
450                                         v[1] = -t;
451                                         v[2] = 1;
452                                         break;
453                                 case 5:
454                                         v[0] = -s;
455                                         v[1] = -t;
456                                         v[2] = -1;
457                                         break;
458                                 }
459                                 intensity = 127.0f / sqrt(DotProduct(v, v));
460                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
461                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
462                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
463                                 data[((side*64+y)*64+x)*4+3] = 255;
464                         }
465                 }
466         }
467         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
468         Mem_Free(data);
469 }
470
471 static void R_BuildFogTexture(void)
472 {
473         int x, b;
474 #define FOGWIDTH 256
475         unsigned char data1[FOGWIDTH][4];
476         //unsigned char data2[FOGWIDTH][4];
477         double d, r, alpha;
478
479         r_refdef.fogmasktable_start = r_refdef.fog_start;
480         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
481         r_refdef.fogmasktable_range = r_refdef.fogrange;
482         r_refdef.fogmasktable_density = r_refdef.fog_density;
483
484         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
485         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
486         {
487                 d = (x * r - r_refdef.fogmasktable_start);
488                 if(developer_extra.integer)
489                         Con_DPrintf("%f ", d);
490                 d = max(0, d);
491                 if (r_fog_exp2.integer)
492                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
493                 else
494                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
495                 if(developer_extra.integer)
496                         Con_DPrintf(" : %f ", alpha);
497                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
498                 if(developer_extra.integer)
499                         Con_DPrintf(" = %f\n", alpha);
500                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
501         }
502
503         for (x = 0;x < FOGWIDTH;x++)
504         {
505                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
506                 data1[x][0] = b;
507                 data1[x][1] = b;
508                 data1[x][2] = b;
509                 data1[x][3] = 255;
510                 //data2[x][0] = 255 - b;
511                 //data2[x][1] = 255 - b;
512                 //data2[x][2] = 255 - b;
513                 //data2[x][3] = 255;
514         }
515         if (r_texture_fogattenuation)
516         {
517                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
518                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
519         }
520         else
521         {
522                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
523                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
524         }
525 }
526
527 static void R_BuildFogHeightTexture(void)
528 {
529         unsigned char *inpixels;
530         int size;
531         int x;
532         int y;
533         int j;
534         float c[4];
535         float f;
536         inpixels = NULL;
537         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
538         if (r_refdef.fogheighttexturename[0])
539                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
540         if (!inpixels)
541         {
542                 r_refdef.fog_height_tablesize = 0;
543                 if (r_texture_fogheighttexture)
544                         R_FreeTexture(r_texture_fogheighttexture);
545                 r_texture_fogheighttexture = NULL;
546                 if (r_refdef.fog_height_table2d)
547                         Mem_Free(r_refdef.fog_height_table2d);
548                 r_refdef.fog_height_table2d = NULL;
549                 if (r_refdef.fog_height_table1d)
550                         Mem_Free(r_refdef.fog_height_table1d);
551                 r_refdef.fog_height_table1d = NULL;
552                 return;
553         }
554         size = image_width;
555         r_refdef.fog_height_tablesize = size;
556         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
557         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
558         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
559         Mem_Free(inpixels);
560         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
561         // average fog color table accounting for every fog layer between a point
562         // and the camera.  (Note: attenuation is handled separately!)
563         for (y = 0;y < size;y++)
564         {
565                 for (x = 0;x < size;x++)
566                 {
567                         Vector4Clear(c);
568                         f = 0;
569                         if (x < y)
570                         {
571                                 for (j = x;j <= y;j++)
572                                 {
573                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
574                                         f++;
575                                 }
576                         }
577                         else
578                         {
579                                 for (j = x;j >= y;j--)
580                                 {
581                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
582                                         f++;
583                                 }
584                         }
585                         f = 1.0f / f;
586                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
587                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
588                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
589                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
590                 }
591         }
592         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
593 }
594
595 //=======================================================================================================================================================
596
597 static const char *builtinshaderstring =
598 #include "shader_glsl.h"
599 ;
600
601 const char *builtinhlslshaderstring =
602 #include "shader_hlsl.h"
603 ;
604
605 char *glslshaderstring = NULL;
606 char *hlslshaderstring = NULL;
607
608 //=======================================================================================================================================================
609
610 typedef struct shaderpermutationinfo_s
611 {
612         const char *pretext;
613         const char *name;
614 }
615 shaderpermutationinfo_t;
616
617 typedef struct shadermodeinfo_s
618 {
619         const char *vertexfilename;
620         const char *geometryfilename;
621         const char *fragmentfilename;
622         const char *pretext;
623         const char *name;
624 }
625 shadermodeinfo_t;
626
627 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
628 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
629 {
630         {"#define USEDIFFUSE\n", " diffuse"},
631         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
632         {"#define USEVIEWTINT\n", " viewtint"},
633         {"#define USECOLORMAPPING\n", " colormapping"},
634         {"#define USESATURATION\n", " saturation"},
635         {"#define USEFOGINSIDE\n", " foginside"},
636         {"#define USEFOGOUTSIDE\n", " fogoutside"},
637         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
638         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
639         {"#define USEGAMMARAMPS\n", " gammaramps"},
640         {"#define USECUBEFILTER\n", " cubefilter"},
641         {"#define USEGLOW\n", " glow"},
642         {"#define USEBLOOM\n", " bloom"},
643         {"#define USESPECULAR\n", " specular"},
644         {"#define USEPOSTPROCESSING\n", " postprocessing"},
645         {"#define USEREFLECTION\n", " reflection"},
646         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
647         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
648         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
649         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
650         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
651         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
652         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
653         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
654         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
655         {"#define USEALPHAKILL\n", " alphakill"},
656         {"#define USEREFLECTCUBE\n", " reflectcube"},
657         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
658         {"#define USEBOUNCEGRID\n", " bouncegrid"},
659         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
660 };
661
662 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
663 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
664 {
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
667         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
681 };
682
683 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
684 {
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
701 };
702
703 struct r_glsl_permutation_s;
704 typedef struct r_glsl_permutation_s
705 {
706         /// hash lookup data
707         struct r_glsl_permutation_s *hashnext;
708         unsigned int mode;
709         unsigned int permutation;
710
711         /// indicates if we have tried compiling this permutation already
712         qboolean compiled;
713         /// 0 if compilation failed
714         int program;
715         // texture units assigned to each detected uniform
716         int tex_Texture_First;
717         int tex_Texture_Second;
718         int tex_Texture_GammaRamps;
719         int tex_Texture_Normal;
720         int tex_Texture_Color;
721         int tex_Texture_Gloss;
722         int tex_Texture_Glow;
723         int tex_Texture_SecondaryNormal;
724         int tex_Texture_SecondaryColor;
725         int tex_Texture_SecondaryGloss;
726         int tex_Texture_SecondaryGlow;
727         int tex_Texture_Pants;
728         int tex_Texture_Shirt;
729         int tex_Texture_FogHeightTexture;
730         int tex_Texture_FogMask;
731         int tex_Texture_Lightmap;
732         int tex_Texture_Deluxemap;
733         int tex_Texture_Attenuation;
734         int tex_Texture_Cube;
735         int tex_Texture_Refraction;
736         int tex_Texture_Reflection;
737         int tex_Texture_ShadowMap2D;
738         int tex_Texture_CubeProjection;
739         int tex_Texture_ScreenDepth;
740         int tex_Texture_ScreenNormalMap;
741         int tex_Texture_ScreenDiffuse;
742         int tex_Texture_ScreenSpecular;
743         int tex_Texture_ReflectMask;
744         int tex_Texture_ReflectCube;
745         int tex_Texture_BounceGrid;
746         /// locations of detected uniforms in program object, or -1 if not found
747         int loc_Texture_First;
748         int loc_Texture_Second;
749         int loc_Texture_GammaRamps;
750         int loc_Texture_Normal;
751         int loc_Texture_Color;
752         int loc_Texture_Gloss;
753         int loc_Texture_Glow;
754         int loc_Texture_SecondaryNormal;
755         int loc_Texture_SecondaryColor;
756         int loc_Texture_SecondaryGloss;
757         int loc_Texture_SecondaryGlow;
758         int loc_Texture_Pants;
759         int loc_Texture_Shirt;
760         int loc_Texture_FogHeightTexture;
761         int loc_Texture_FogMask;
762         int loc_Texture_Lightmap;
763         int loc_Texture_Deluxemap;
764         int loc_Texture_Attenuation;
765         int loc_Texture_Cube;
766         int loc_Texture_Refraction;
767         int loc_Texture_Reflection;
768         int loc_Texture_ShadowMap2D;
769         int loc_Texture_CubeProjection;
770         int loc_Texture_ScreenDepth;
771         int loc_Texture_ScreenNormalMap;
772         int loc_Texture_ScreenDiffuse;
773         int loc_Texture_ScreenSpecular;
774         int loc_Texture_ReflectMask;
775         int loc_Texture_ReflectCube;
776         int loc_Texture_BounceGrid;
777         int loc_Alpha;
778         int loc_BloomBlur_Parameters;
779         int loc_ClientTime;
780         int loc_Color_Ambient;
781         int loc_Color_Diffuse;
782         int loc_Color_Specular;
783         int loc_Color_Glow;
784         int loc_Color_Pants;
785         int loc_Color_Shirt;
786         int loc_DeferredColor_Ambient;
787         int loc_DeferredColor_Diffuse;
788         int loc_DeferredColor_Specular;
789         int loc_DeferredMod_Diffuse;
790         int loc_DeferredMod_Specular;
791         int loc_DistortScaleRefractReflect;
792         int loc_EyePosition;
793         int loc_FogColor;
794         int loc_FogHeightFade;
795         int loc_FogPlane;
796         int loc_FogPlaneViewDist;
797         int loc_FogRangeRecip;
798         int loc_LightColor;
799         int loc_LightDir;
800         int loc_LightPosition;
801         int loc_OffsetMapping_ScaleSteps;
802         int loc_PixelSize;
803         int loc_ReflectColor;
804         int loc_ReflectFactor;
805         int loc_ReflectOffset;
806         int loc_RefractColor;
807         int loc_Saturation;
808         int loc_ScreenCenterRefractReflect;
809         int loc_ScreenScaleRefractReflect;
810         int loc_ScreenToDepth;
811         int loc_ShadowMap_Parameters;
812         int loc_ShadowMap_TextureScale;
813         int loc_SpecularPower;
814         int loc_UserVec1;
815         int loc_UserVec2;
816         int loc_UserVec3;
817         int loc_UserVec4;
818         int loc_ViewTintColor;
819         int loc_ViewToLight;
820         int loc_ModelToLight;
821         int loc_TexMatrix;
822         int loc_BackgroundTexMatrix;
823         int loc_ModelViewProjectionMatrix;
824         int loc_ModelViewMatrix;
825         int loc_PixelToScreenTexCoord;
826         int loc_ModelToReflectCube;
827         int loc_ShadowMapMatrix;
828         int loc_BloomColorSubtract;
829         int loc_NormalmapScrollBlend;
830         int loc_BounceGridMatrix;
831         int loc_BounceGridIntensity;
832 }
833 r_glsl_permutation_t;
834
835 #define SHADERPERMUTATION_HASHSIZE 256
836
837
838 // non-degradable "lightweight" shader parameters to keep the permutations simpler
839 // these can NOT degrade! only use for simple stuff
840 enum
841 {
842         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
843         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
844         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
845         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
846         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
847         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
848 };
849 #define SHADERSTATICPARMS_COUNT 6
850
851 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
852 static int shaderstaticparms_count = 0;
853
854 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
855 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
856 qboolean R_CompileShader_CheckStaticParms(void)
857 {
858         static int r_compileshader_staticparms_save[1];
859         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
860         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
861
862         // detect all
863         if (r_glsl_saturation_redcompensate.integer)
864                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
865         if (r_shadow_glossexact.integer)
866                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
867         if (r_glsl_postprocess.integer)
868         {
869                 if (r_glsl_postprocess_uservec1_enable.integer)
870                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
871                 if (r_glsl_postprocess_uservec2_enable.integer)
872                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
873                 if (r_glsl_postprocess_uservec3_enable.integer)
874                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
875                 if (r_glsl_postprocess_uservec4_enable.integer)
876                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
877         }
878         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
879 }
880
881 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
882         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
883                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
884         else \
885                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
886 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
887 {
888         shaderstaticparms_count = 0;
889
890         // emit all
891         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
892         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
893         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
894         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
895         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
896         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
897 }
898
899 /// information about each possible shader permutation
900 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
901 /// currently selected permutation
902 r_glsl_permutation_t *r_glsl_permutation;
903 /// storage for permutations linked in the hash table
904 memexpandablearray_t r_glsl_permutationarray;
905
906 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
907 {
908         //unsigned int hashdepth = 0;
909         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
910         r_glsl_permutation_t *p;
911         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
912         {
913                 if (p->mode == mode && p->permutation == permutation)
914                 {
915                         //if (hashdepth > 10)
916                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
917                         return p;
918                 }
919                 //hashdepth++;
920         }
921         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
922         p->mode = mode;
923         p->permutation = permutation;
924         p->hashnext = r_glsl_permutationhash[mode][hashindex];
925         r_glsl_permutationhash[mode][hashindex] = p;
926         //if (hashdepth > 10)
927         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
928         return p;
929 }
930
931 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
932 {
933         char *shaderstring;
934         if (!filename || !filename[0])
935                 return NULL;
936         if (!strcmp(filename, "glsl/default.glsl"))
937         {
938                 if (!glslshaderstring)
939                 {
940                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
941                         if (glslshaderstring)
942                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
943                         else
944                                 glslshaderstring = (char *)builtinshaderstring;
945                 }
946                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
947                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
948                 return shaderstring;
949         }
950         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
951         if (shaderstring)
952         {
953                 if (printfromdisknotice)
954                         Con_DPrintf("from disk %s... ", filename);
955                 return shaderstring;
956         }
957         return shaderstring;
958 }
959
960 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
961 {
962         int i;
963         int sampler;
964         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
965         char *vertexstring, *geometrystring, *fragmentstring;
966         char permutationname[256];
967         int vertstrings_count = 0;
968         int geomstrings_count = 0;
969         int fragstrings_count = 0;
970         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
971         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
972         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
973
974         if (p->compiled)
975                 return;
976         p->compiled = true;
977         p->program = 0;
978
979         permutationname[0] = 0;
980         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
981         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
982         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
983
984         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
985
986         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
987         if(vid.support.gl20shaders130)
988         {
989                 vertstrings_list[vertstrings_count++] = "#version 130\n";
990                 geomstrings_list[geomstrings_count++] = "#version 130\n";
991                 fragstrings_list[fragstrings_count++] = "#version 130\n";
992         }
993
994         // the first pretext is which type of shader to compile as
995         // (later these will all be bound together as a program object)
996         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
997         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
998         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
999
1000         // the second pretext is the mode (for example a light source)
1001         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1002         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1003         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1004         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1005
1006         // now add all the permutation pretexts
1007         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1008         {
1009                 if (permutation & (1<<i))
1010                 {
1011                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1012                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1013                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1014                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1015                 }
1016                 else
1017                 {
1018                         // keep line numbers correct
1019                         vertstrings_list[vertstrings_count++] = "\n";
1020                         geomstrings_list[geomstrings_count++] = "\n";
1021                         fragstrings_list[fragstrings_count++] = "\n";
1022                 }
1023         }
1024
1025         // add static parms
1026         R_CompileShader_AddStaticParms(mode, permutation);
1027         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1028         vertstrings_count += shaderstaticparms_count;
1029         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1030         geomstrings_count += shaderstaticparms_count;
1031         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1032         fragstrings_count += shaderstaticparms_count;
1033
1034         // now append the shader text itself
1035         vertstrings_list[vertstrings_count++] = vertexstring;
1036         geomstrings_list[geomstrings_count++] = geometrystring;
1037         fragstrings_list[fragstrings_count++] = fragmentstring;
1038
1039         // if any sources were NULL, clear the respective list
1040         if (!vertexstring)
1041                 vertstrings_count = 0;
1042         if (!geometrystring)
1043                 geomstrings_count = 0;
1044         if (!fragmentstring)
1045                 fragstrings_count = 0;
1046
1047         // compile the shader program
1048         if (vertstrings_count + geomstrings_count + fragstrings_count)
1049                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1050         if (p->program)
1051         {
1052                 CHECKGLERROR
1053                 qglUseProgram(p->program);CHECKGLERROR
1054                 // look up all the uniform variable names we care about, so we don't
1055                 // have to look them up every time we set them
1056
1057                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1058                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1059                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1060                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1061                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1062                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1063                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1064                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1065                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1066                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1067                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1068                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1069                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1070                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1071                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1072                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1073                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1074                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1075                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1076                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1077                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1078                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1079                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1080                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1081                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1082                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1083                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1084                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1085                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1086                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1087                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1088                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1089                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1090                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1091                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1092                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1093                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1094                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1095                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1096                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1097                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1098                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1099                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1100                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1101                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1102                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1103                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1104                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1105                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1106                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1107                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1108                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1109                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1110                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1111                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1112                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1113                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1114                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1115                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1116                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1117                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1118                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1119                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1120                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1121                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1122                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1123                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1124                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1125                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1126                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1127                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1128                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1129                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1130                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1131                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1132                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1133                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1134                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1135                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1136                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1137                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1138                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1139                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1140                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1141                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1142                 // initialize the samplers to refer to the texture units we use
1143                 p->tex_Texture_First = -1;
1144                 p->tex_Texture_Second = -1;
1145                 p->tex_Texture_GammaRamps = -1;
1146                 p->tex_Texture_Normal = -1;
1147                 p->tex_Texture_Color = -1;
1148                 p->tex_Texture_Gloss = -1;
1149                 p->tex_Texture_Glow = -1;
1150                 p->tex_Texture_SecondaryNormal = -1;
1151                 p->tex_Texture_SecondaryColor = -1;
1152                 p->tex_Texture_SecondaryGloss = -1;
1153                 p->tex_Texture_SecondaryGlow = -1;
1154                 p->tex_Texture_Pants = -1;
1155                 p->tex_Texture_Shirt = -1;
1156                 p->tex_Texture_FogHeightTexture = -1;
1157                 p->tex_Texture_FogMask = -1;
1158                 p->tex_Texture_Lightmap = -1;
1159                 p->tex_Texture_Deluxemap = -1;
1160                 p->tex_Texture_Attenuation = -1;
1161                 p->tex_Texture_Cube = -1;
1162                 p->tex_Texture_Refraction = -1;
1163                 p->tex_Texture_Reflection = -1;
1164                 p->tex_Texture_ShadowMap2D = -1;
1165                 p->tex_Texture_CubeProjection = -1;
1166                 p->tex_Texture_ScreenDepth = -1;
1167                 p->tex_Texture_ScreenNormalMap = -1;
1168                 p->tex_Texture_ScreenDiffuse = -1;
1169                 p->tex_Texture_ScreenSpecular = -1;
1170                 p->tex_Texture_ReflectMask = -1;
1171                 p->tex_Texture_ReflectCube = -1;
1172                 p->tex_Texture_BounceGrid = -1;
1173                 sampler = 0;
1174                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1175                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1176                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1177                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1178                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1179                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1180                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1181                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1182                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1183                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1184                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1185                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1186                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1187                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1188                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1189                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1190                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1191                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1192                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1193                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1194                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1195                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1196                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1197                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1198                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1199                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1200                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1201                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1202                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1203                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1204                 CHECKGLERROR
1205                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1206         }
1207         else
1208                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1209
1210         // free the strings
1211         if (vertexstring)
1212                 Mem_Free(vertexstring);
1213         if (geometrystring)
1214                 Mem_Free(geometrystring);
1215         if (fragmentstring)
1216                 Mem_Free(fragmentstring);
1217 }
1218
1219 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1220 {
1221         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1222         if (r_glsl_permutation != perm)
1223         {
1224                 r_glsl_permutation = perm;
1225                 if (!r_glsl_permutation->program)
1226                 {
1227                         if (!r_glsl_permutation->compiled)
1228                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1229                         if (!r_glsl_permutation->program)
1230                         {
1231                                 // remove features until we find a valid permutation
1232                                 int i;
1233                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1234                                 {
1235                                         // reduce i more quickly whenever it would not remove any bits
1236                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1237                                         if (!(permutation & j))
1238                                                 continue;
1239                                         permutation -= j;
1240                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1241                                         if (!r_glsl_permutation->compiled)
1242                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1243                                         if (r_glsl_permutation->program)
1244                                                 break;
1245                                 }
1246                                 if (i >= SHADERPERMUTATION_COUNT)
1247                                 {
1248                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1249                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1250                                         qglUseProgram(0);CHECKGLERROR
1251                                         return; // no bit left to clear, entire mode is broken
1252                                 }
1253                         }
1254                 }
1255                 CHECKGLERROR
1256                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1257         }
1258         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1259         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1260         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1261 }
1262
1263 #ifdef SUPPORTD3D
1264
1265 #ifdef SUPPORTD3D
1266 #include <d3d9.h>
1267 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1268 extern D3DCAPS9 vid_d3d9caps;
1269 #endif
1270
1271 struct r_hlsl_permutation_s;
1272 typedef struct r_hlsl_permutation_s
1273 {
1274         /// hash lookup data
1275         struct r_hlsl_permutation_s *hashnext;
1276         unsigned int mode;
1277         unsigned int permutation;
1278
1279         /// indicates if we have tried compiling this permutation already
1280         qboolean compiled;
1281         /// NULL if compilation failed
1282         IDirect3DVertexShader9 *vertexshader;
1283         IDirect3DPixelShader9 *pixelshader;
1284 }
1285 r_hlsl_permutation_t;
1286
1287 typedef enum D3DVSREGISTER_e
1288 {
1289         D3DVSREGISTER_TexMatrix = 0, // float4x4
1290         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1291         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1292         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1293         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1294         D3DVSREGISTER_ModelToLight = 20, // float4x4
1295         D3DVSREGISTER_EyePosition = 24,
1296         D3DVSREGISTER_FogPlane = 25,
1297         D3DVSREGISTER_LightDir = 26,
1298         D3DVSREGISTER_LightPosition = 27,
1299 }
1300 D3DVSREGISTER_t;
1301
1302 typedef enum D3DPSREGISTER_e
1303 {
1304         D3DPSREGISTER_Alpha = 0,
1305         D3DPSREGISTER_BloomBlur_Parameters = 1,
1306         D3DPSREGISTER_ClientTime = 2,
1307         D3DPSREGISTER_Color_Ambient = 3,
1308         D3DPSREGISTER_Color_Diffuse = 4,
1309         D3DPSREGISTER_Color_Specular = 5,
1310         D3DPSREGISTER_Color_Glow = 6,
1311         D3DPSREGISTER_Color_Pants = 7,
1312         D3DPSREGISTER_Color_Shirt = 8,
1313         D3DPSREGISTER_DeferredColor_Ambient = 9,
1314         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1315         D3DPSREGISTER_DeferredColor_Specular = 11,
1316         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1317         D3DPSREGISTER_DeferredMod_Specular = 13,
1318         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1319         D3DPSREGISTER_EyePosition = 15, // unused
1320         D3DPSREGISTER_FogColor = 16,
1321         D3DPSREGISTER_FogHeightFade = 17,
1322         D3DPSREGISTER_FogPlane = 18,
1323         D3DPSREGISTER_FogPlaneViewDist = 19,
1324         D3DPSREGISTER_FogRangeRecip = 20,
1325         D3DPSREGISTER_LightColor = 21,
1326         D3DPSREGISTER_LightDir = 22, // unused
1327         D3DPSREGISTER_LightPosition = 23,
1328         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1329         D3DPSREGISTER_PixelSize = 25,
1330         D3DPSREGISTER_ReflectColor = 26,
1331         D3DPSREGISTER_ReflectFactor = 27,
1332         D3DPSREGISTER_ReflectOffset = 28,
1333         D3DPSREGISTER_RefractColor = 29,
1334         D3DPSREGISTER_Saturation = 30,
1335         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1336         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1337         D3DPSREGISTER_ScreenToDepth = 33,
1338         D3DPSREGISTER_ShadowMap_Parameters = 34,
1339         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1340         D3DPSREGISTER_SpecularPower = 36,
1341         D3DPSREGISTER_UserVec1 = 37,
1342         D3DPSREGISTER_UserVec2 = 38,
1343         D3DPSREGISTER_UserVec3 = 39,
1344         D3DPSREGISTER_UserVec4 = 40,
1345         D3DPSREGISTER_ViewTintColor = 41,
1346         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1347         D3DPSREGISTER_BloomColorSubtract = 43,
1348         D3DPSREGISTER_ViewToLight = 44, // float4x4
1349         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1350         D3DPSREGISTER_NormalmapScrollBlend = 52,
1351         // next at 53
1352 }
1353 D3DPSREGISTER_t;
1354
1355 /// information about each possible shader permutation
1356 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1357 /// currently selected permutation
1358 r_hlsl_permutation_t *r_hlsl_permutation;
1359 /// storage for permutations linked in the hash table
1360 memexpandablearray_t r_hlsl_permutationarray;
1361
1362 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1363 {
1364         //unsigned int hashdepth = 0;
1365         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1366         r_hlsl_permutation_t *p;
1367         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1368         {
1369                 if (p->mode == mode && p->permutation == permutation)
1370                 {
1371                         //if (hashdepth > 10)
1372                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1373                         return p;
1374                 }
1375                 //hashdepth++;
1376         }
1377         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1378         p->mode = mode;
1379         p->permutation = permutation;
1380         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1381         r_hlsl_permutationhash[mode][hashindex] = p;
1382         //if (hashdepth > 10)
1383         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1384         return p;
1385 }
1386
1387 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1388 {
1389         char *shaderstring;
1390         if (!filename || !filename[0])
1391                 return NULL;
1392         if (!strcmp(filename, "hlsl/default.hlsl"))
1393         {
1394                 if (!hlslshaderstring)
1395                 {
1396                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1397                         if (hlslshaderstring)
1398                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1399                         else
1400                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1401                 }
1402                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1403                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1404                 return shaderstring;
1405         }
1406         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1407         if (shaderstring)
1408         {
1409                 if (printfromdisknotice)
1410                         Con_DPrintf("from disk %s... ", filename);
1411                 return shaderstring;
1412         }
1413         return shaderstring;
1414 }
1415
1416 #include <d3dx9.h>
1417 //#include <d3dx9shader.h>
1418 //#include <d3dx9mesh.h>
1419
1420 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1421 {
1422         DWORD *vsbin = NULL;
1423         DWORD *psbin = NULL;
1424         fs_offset_t vsbinsize;
1425         fs_offset_t psbinsize;
1426 //      IDirect3DVertexShader9 *vs = NULL;
1427 //      IDirect3DPixelShader9 *ps = NULL;
1428         ID3DXBuffer *vslog = NULL;
1429         ID3DXBuffer *vsbuffer = NULL;
1430         ID3DXConstantTable *vsconstanttable = NULL;
1431         ID3DXBuffer *pslog = NULL;
1432         ID3DXBuffer *psbuffer = NULL;
1433         ID3DXConstantTable *psconstanttable = NULL;
1434         int vsresult = 0;
1435         int psresult = 0;
1436         char temp[MAX_INPUTLINE];
1437         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1438         qboolean debugshader = gl_paranoid.integer != 0;
1439         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1440         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1441         if (!debugshader)
1442         {
1443                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1444                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1445         }
1446         if ((!vsbin && vertstring) || (!psbin && fragstring))
1447         {
1448                 const char* dllnames_d3dx9 [] =
1449                 {
1450                         "d3dx9_43.dll",
1451                         "d3dx9_42.dll",
1452                         "d3dx9_41.dll",
1453                         "d3dx9_40.dll",
1454                         "d3dx9_39.dll",
1455                         "d3dx9_38.dll",
1456                         "d3dx9_37.dll",
1457                         "d3dx9_36.dll",
1458                         "d3dx9_35.dll",
1459                         "d3dx9_34.dll",
1460                         "d3dx9_33.dll",
1461                         "d3dx9_32.dll",
1462                         "d3dx9_31.dll",
1463                         "d3dx9_30.dll",
1464                         "d3dx9_29.dll",
1465                         "d3dx9_28.dll",
1466                         "d3dx9_27.dll",
1467                         "d3dx9_26.dll",
1468                         "d3dx9_25.dll",
1469                         "d3dx9_24.dll",
1470                         NULL
1471                 };
1472                 dllhandle_t d3dx9_dll = NULL;
1473                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1474                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1475                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1476                 dllfunction_t d3dx9_dllfuncs[] =
1477                 {
1478                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1479                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1480                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1481                         {NULL, NULL}
1482                 };
1483                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1484                 {
1485                         DWORD shaderflags = 0;
1486                         if (debugshader)
1487                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1488                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1489                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1490                         if (vertstring && vertstring[0])
1491                         {
1492                                 if (debugshader)
1493                                 {
1494 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1495 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1496                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1497                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1498                                 }
1499                                 else
1500                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1501                                 if (vsbuffer)
1502                                 {
1503                                         vsbinsize = vsbuffer->GetBufferSize();
1504                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1505                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1506                                         vsbuffer->Release();
1507                                 }
1508                                 if (vslog)
1509                                 {
1510                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1511                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1512                                         vslog->Release();
1513                                 }
1514                         }
1515                         if (fragstring && fragstring[0])
1516                         {
1517                                 if (debugshader)
1518                                 {
1519 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1520 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1521                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1522                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1523                                 }
1524                                 else
1525                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1526                                 if (psbuffer)
1527                                 {
1528                                         psbinsize = psbuffer->GetBufferSize();
1529                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1530                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1531                                         psbuffer->Release();
1532                                 }
1533                                 if (pslog)
1534                                 {
1535                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1536                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1537                                         pslog->Release();
1538                                 }
1539                         }
1540                         Sys_UnloadLibrary(&d3dx9_dll);
1541                 }
1542                 else
1543                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1544         }
1545         if (vsbin && psbin)
1546         {
1547                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1548                 if (FAILED(vsresult))
1549                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1550                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1551                 if (FAILED(psresult))
1552                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1553         }
1554         // free the shader data
1555         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1556         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1557 }
1558
1559 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1560 {
1561         int i;
1562         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1563         int vertstring_length = 0;
1564         int geomstring_length = 0;
1565         int fragstring_length = 0;
1566         char *t;
1567         char *vertexstring, *geometrystring, *fragmentstring;
1568         char *vertstring, *geomstring, *fragstring;
1569         char permutationname[256];
1570         char cachename[256];
1571         int vertstrings_count = 0;
1572         int geomstrings_count = 0;
1573         int fragstrings_count = 0;
1574         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1575         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1576         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1577
1578         if (p->compiled)
1579                 return;
1580         p->compiled = true;
1581         p->vertexshader = NULL;
1582         p->pixelshader = NULL;
1583
1584         permutationname[0] = 0;
1585         cachename[0] = 0;
1586         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1587         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1588         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1589
1590         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1591         strlcat(cachename, "hlsl/", sizeof(cachename));
1592
1593         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1594         vertstrings_count = 0;
1595         geomstrings_count = 0;
1596         fragstrings_count = 0;
1597         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1598         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1599         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1600
1601         // the first pretext is which type of shader to compile as
1602         // (later these will all be bound together as a program object)
1603         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1604         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1605         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1606
1607         // the second pretext is the mode (for example a light source)
1608         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1609         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1610         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1611         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1612         strlcat(cachename, modeinfo->name, sizeof(cachename));
1613
1614         // now add all the permutation pretexts
1615         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1616         {
1617                 if (permutation & (1<<i))
1618                 {
1619                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1620                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1621                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1622                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1623                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1624                 }
1625                 else
1626                 {
1627                         // keep line numbers correct
1628                         vertstrings_list[vertstrings_count++] = "\n";
1629                         geomstrings_list[geomstrings_count++] = "\n";
1630                         fragstrings_list[fragstrings_count++] = "\n";
1631                 }
1632         }
1633
1634         // add static parms
1635         R_CompileShader_AddStaticParms(mode, permutation);
1636         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1637         vertstrings_count += shaderstaticparms_count;
1638         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1639         geomstrings_count += shaderstaticparms_count;
1640         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1641         fragstrings_count += shaderstaticparms_count;
1642
1643         // replace spaces in the cachename with _ characters
1644         for (i = 0;cachename[i];i++)
1645                 if (cachename[i] == ' ')
1646                         cachename[i] = '_';
1647
1648         // now append the shader text itself
1649         vertstrings_list[vertstrings_count++] = vertexstring;
1650         geomstrings_list[geomstrings_count++] = geometrystring;
1651         fragstrings_list[fragstrings_count++] = fragmentstring;
1652
1653         // if any sources were NULL, clear the respective list
1654         if (!vertexstring)
1655                 vertstrings_count = 0;
1656         if (!geometrystring)
1657                 geomstrings_count = 0;
1658         if (!fragmentstring)
1659                 fragstrings_count = 0;
1660
1661         vertstring_length = 0;
1662         for (i = 0;i < vertstrings_count;i++)
1663                 vertstring_length += strlen(vertstrings_list[i]);
1664         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1665         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1666                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1667
1668         geomstring_length = 0;
1669         for (i = 0;i < geomstrings_count;i++)
1670                 geomstring_length += strlen(geomstrings_list[i]);
1671         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1672         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1673                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1674
1675         fragstring_length = 0;
1676         for (i = 0;i < fragstrings_count;i++)
1677                 fragstring_length += strlen(fragstrings_list[i]);
1678         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1679         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1680                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1681
1682         // try to load the cached shader, or generate one
1683         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1684
1685         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1686                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1687         else
1688                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1689
1690         // free the strings
1691         if (vertstring)
1692                 Mem_Free(vertstring);
1693         if (geomstring)
1694                 Mem_Free(geomstring);
1695         if (fragstring)
1696                 Mem_Free(fragstring);
1697         if (vertexstring)
1698                 Mem_Free(vertexstring);
1699         if (geometrystring)
1700                 Mem_Free(geometrystring);
1701         if (fragmentstring)
1702                 Mem_Free(fragmentstring);
1703 }
1704
1705 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1706 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1707 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);}
1708 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);}
1709 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);}
1710 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);}
1711
1712 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1713 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1714 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);}
1715 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);}
1716 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);}
1717 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);}
1718
1719 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1720 {
1721         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1722         if (r_hlsl_permutation != perm)
1723         {
1724                 r_hlsl_permutation = perm;
1725                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1726                 {
1727                         if (!r_hlsl_permutation->compiled)
1728                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1729                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1730                         {
1731                                 // remove features until we find a valid permutation
1732                                 int i;
1733                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1734                                 {
1735                                         // reduce i more quickly whenever it would not remove any bits
1736                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1737                                         if (!(permutation & j))
1738                                                 continue;
1739                                         permutation -= j;
1740                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1741                                         if (!r_hlsl_permutation->compiled)
1742                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1743                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1744                                                 break;
1745                                 }
1746                                 if (i >= SHADERPERMUTATION_COUNT)
1747                                 {
1748                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1749                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1750                                         return; // no bit left to clear, entire mode is broken
1751                                 }
1752                         }
1753                 }
1754                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1755                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1756         }
1757         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1758         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1759         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1760 }
1761 #endif
1762
1763 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1764 {
1765         DPSOFTRAST_SetShader(mode, permutation);
1766         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1767         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1768         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1769 }
1770
1771 void R_GLSL_Restart_f(void)
1772 {
1773         unsigned int i, limit;
1774         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1775                 Mem_Free(glslshaderstring);
1776         glslshaderstring = NULL;
1777         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1778                 Mem_Free(hlslshaderstring);
1779         hlslshaderstring = NULL;
1780         switch(vid.renderpath)
1781         {
1782         case RENDERPATH_D3D9:
1783 #ifdef SUPPORTD3D
1784                 {
1785                         r_hlsl_permutation_t *p;
1786                         r_hlsl_permutation = NULL;
1787                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1788                         for (i = 0;i < limit;i++)
1789                         {
1790                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1791                                 {
1792                                         if (p->vertexshader)
1793                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1794                                         if (p->pixelshader)
1795                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1796                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1797                                 }
1798                         }
1799                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1800                 }
1801 #endif
1802                 break;
1803         case RENDERPATH_D3D10:
1804                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1805                 break;
1806         case RENDERPATH_D3D11:
1807                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1808                 break;
1809         case RENDERPATH_GL20:
1810         case RENDERPATH_GLES2:
1811                 {
1812                         r_glsl_permutation_t *p;
1813                         r_glsl_permutation = NULL;
1814                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1815                         for (i = 0;i < limit;i++)
1816                         {
1817                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1818                                 {
1819                                         GL_Backend_FreeProgram(p->program);
1820                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1821                                 }
1822                         }
1823                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1824                 }
1825                 break;
1826         case RENDERPATH_GL13:
1827         case RENDERPATH_GL11:
1828                 break;
1829         case RENDERPATH_SOFT:
1830                 break;
1831         }
1832 }
1833
1834 void R_GLSL_DumpShader_f(void)
1835 {
1836         int i;
1837         qfile_t *file;
1838
1839         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1840         if (file)
1841         {
1842                 FS_Print(file, "/* The engine may define the following macros:\n");
1843                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1844                 for (i = 0;i < SHADERMODE_COUNT;i++)
1845                         FS_Print(file, glslshadermodeinfo[i].pretext);
1846                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1847                         FS_Print(file, shaderpermutationinfo[i].pretext);
1848                 FS_Print(file, "*/\n");
1849                 FS_Print(file, builtinshaderstring);
1850                 FS_Close(file);
1851                 Con_Printf("glsl/default.glsl written\n");
1852         }
1853         else
1854                 Con_Printf("failed to write to glsl/default.glsl\n");
1855
1856         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1857         if (file)
1858         {
1859                 FS_Print(file, "/* The engine may define the following macros:\n");
1860                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1861                 for (i = 0;i < SHADERMODE_COUNT;i++)
1862                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1863                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1864                         FS_Print(file, shaderpermutationinfo[i].pretext);
1865                 FS_Print(file, "*/\n");
1866                 FS_Print(file, builtinhlslshaderstring);
1867                 FS_Close(file);
1868                 Con_Printf("hlsl/default.hlsl written\n");
1869         }
1870         else
1871                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1872 }
1873
1874 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1875 {
1876         if (!second)
1877                 texturemode = GL_MODULATE;
1878         switch (vid.renderpath)
1879         {
1880         case RENDERPATH_D3D9:
1881 #ifdef SUPPORTD3D
1882                 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))));
1883                 R_Mesh_TexBind(GL20TU_FIRST , first );
1884                 R_Mesh_TexBind(GL20TU_SECOND, second);
1885 #endif
1886                 break;
1887         case RENDERPATH_D3D10:
1888                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1889                 break;
1890         case RENDERPATH_D3D11:
1891                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1892                 break;
1893         case RENDERPATH_GL20:
1894         case RENDERPATH_GLES2:
1895                 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))));
1896                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1897                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1898                 break;
1899         case RENDERPATH_GL13:
1900                 R_Mesh_TexBind(0, first );
1901                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1902                 R_Mesh_TexBind(1, second);
1903                 if (second)
1904                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1905                 break;
1906         case RENDERPATH_GL11:
1907                 R_Mesh_TexBind(0, first );
1908                 break;
1909         case RENDERPATH_SOFT:
1910                 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))));
1911                 R_Mesh_TexBind(GL20TU_FIRST , first );
1912                 R_Mesh_TexBind(GL20TU_SECOND, second);
1913                 break;
1914         }
1915 }
1916
1917 void R_SetupShader_DepthOrShadow(void)
1918 {
1919         switch (vid.renderpath)
1920         {
1921         case RENDERPATH_D3D9:
1922 #ifdef SUPPORTD3D
1923                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1924 #endif
1925                 break;
1926         case RENDERPATH_D3D10:
1927                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1928                 break;
1929         case RENDERPATH_D3D11:
1930                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1931                 break;
1932         case RENDERPATH_GL20:
1933         case RENDERPATH_GLES2:
1934                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1935                 break;
1936         case RENDERPATH_GL13:
1937                 R_Mesh_TexBind(0, 0);
1938                 R_Mesh_TexBind(1, 0);
1939                 break;
1940         case RENDERPATH_GL11:
1941                 R_Mesh_TexBind(0, 0);
1942                 break;
1943         case RENDERPATH_SOFT:
1944                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1945                 break;
1946         }
1947 }
1948
1949 void R_SetupShader_ShowDepth(void)
1950 {
1951         switch (vid.renderpath)
1952         {
1953         case RENDERPATH_D3D9:
1954 #ifdef SUPPORTHLSL
1955                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1956 #endif
1957                 break;
1958         case RENDERPATH_D3D10:
1959                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1960                 break;
1961         case RENDERPATH_D3D11:
1962                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1963                 break;
1964         case RENDERPATH_GL20:
1965         case RENDERPATH_GLES2:
1966                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1967                 break;
1968         case RENDERPATH_GL13:
1969                 break;
1970         case RENDERPATH_GL11:
1971                 break;
1972         case RENDERPATH_SOFT:
1973                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1974                 break;
1975         }
1976 }
1977
1978 extern qboolean r_shadow_usingdeferredprepass;
1979 extern cvar_t r_shadow_deferred_8bitrange;
1980 extern rtexture_t *r_shadow_attenuationgradienttexture;
1981 extern rtexture_t *r_shadow_attenuation2dtexture;
1982 extern rtexture_t *r_shadow_attenuation3dtexture;
1983 extern qboolean r_shadow_usingshadowmap2d;
1984 extern qboolean r_shadow_usingshadowmaportho;
1985 extern float r_shadow_shadowmap_texturescale[2];
1986 extern float r_shadow_shadowmap_parameters[4];
1987 extern qboolean r_shadow_shadowmapvsdct;
1988 extern qboolean r_shadow_shadowmapsampler;
1989 extern int r_shadow_shadowmappcf;
1990 extern rtexture_t *r_shadow_shadowmap2dtexture;
1991 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1992 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1993 extern matrix4x4_t r_shadow_shadowmapmatrix;
1994 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1995 extern int r_shadow_prepass_width;
1996 extern int r_shadow_prepass_height;
1997 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1998 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1999 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2000 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2001 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2002
2003 #define BLENDFUNC_ALLOWS_COLORMOD      1
2004 #define BLENDFUNC_ALLOWS_FOG           2
2005 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2006 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2007 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2008 static int R_BlendFuncFlags(int src, int dst)
2009 {
2010         int r = 0;
2011
2012         // a blendfunc allows colormod if:
2013         // a) it can never keep the destination pixel invariant, or
2014         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2015         // this is to prevent unintended side effects from colormod
2016
2017         // a blendfunc allows fog if:
2018         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2019         // this is to prevent unintended side effects from fog
2020
2021         // these checks are the output of fogeval.pl
2022
2023         r |= BLENDFUNC_ALLOWS_COLORMOD;
2024         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2025         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2026         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2027         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2028         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2029         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2030         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2031         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2032         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2033         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2034         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2035         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2036         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2037         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2038         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2039         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2040         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2041         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2042         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2043         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2044         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2045
2046         return r;
2047 }
2048
2049 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)
2050 {
2051         // select a permutation of the lighting shader appropriate to this
2052         // combination of texture, entity, light source, and fogging, only use the
2053         // minimum features necessary to avoid wasting rendering time in the
2054         // fragment shader on features that are not being used
2055         unsigned int permutation = 0;
2056         unsigned int mode = 0;
2057         int blendfuncflags;
2058         static float dummy_colormod[3] = {1, 1, 1};
2059         float *colormod = rsurface.colormod;
2060         float m16f[16];
2061         matrix4x4_t tempmatrix;
2062         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2063         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2064                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2065         if (rsurfacepass == RSURFPASS_BACKGROUND)
2066         {
2067                 // distorted background
2068                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2069                 {
2070                         mode = SHADERMODE_WATER;
2071                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2072                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2073                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2074                         {
2075                                 // this is the right thing to do for wateralpha
2076                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2077                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2078                         }
2079                         else
2080                         {
2081                                 // this is the right thing to do for entity alpha
2082                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2083                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2084                         }
2085                 }
2086                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2087                 {
2088                         mode = SHADERMODE_REFRACTION;
2089                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2090                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2091                 }
2092                 else
2093                 {
2094                         mode = SHADERMODE_GENERIC;
2095                         permutation |= SHADERPERMUTATION_DIFFUSE;
2096                         GL_BlendFunc(GL_ONE, GL_ZERO);
2097                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2098                 }
2099         }
2100         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2101         {
2102                 if (r_glsl_offsetmapping.integer)
2103                 {
2104                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2105                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2106                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2107                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2108                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2109                         {
2110                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2111                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2112                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2113                         }
2114                 }
2115                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2116                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2117                 // normalmap (deferred prepass), may use alpha test on diffuse
2118                 mode = SHADERMODE_DEFERREDGEOMETRY;
2119                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2120                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2121                 GL_BlendFunc(GL_ONE, GL_ZERO);
2122                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2123         }
2124         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2125         {
2126                 if (r_glsl_offsetmapping.integer)
2127                 {
2128                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2129                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2130                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2131                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2132                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2133                         {
2134                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2135                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2136                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2137                         }
2138                 }
2139                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2140                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2141                 // light source
2142                 mode = SHADERMODE_LIGHTSOURCE;
2143                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2144                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2145                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2146                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2147                 if (diffusescale > 0)
2148                         permutation |= SHADERPERMUTATION_DIFFUSE;
2149                 if (specularscale > 0)
2150                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2151                 if (r_refdef.fogenabled)
2152                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2153                 if (rsurface.texture->colormapping)
2154                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2155                 if (r_shadow_usingshadowmap2d)
2156                 {
2157                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2158                         if(r_shadow_shadowmapvsdct)
2159                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2160
2161                         if (r_shadow_shadowmapsampler)
2162                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2163                         if (r_shadow_shadowmappcf > 1)
2164                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2165                         else if (r_shadow_shadowmappcf)
2166                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2167                 }
2168                 if (rsurface.texture->reflectmasktexture)
2169                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2170                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2171                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2172         }
2173         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2174         {
2175                 if (r_glsl_offsetmapping.integer)
2176                 {
2177                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2178                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2179                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2180                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2181                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2182                         {
2183                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2184                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2185                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2186                         }
2187                 }
2188                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2189                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2190                 // unshaded geometry (fullbright or ambient model lighting)
2191                 mode = SHADERMODE_FLATCOLOR;
2192                 ambientscale = diffusescale = specularscale = 0;
2193                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2194                         permutation |= SHADERPERMUTATION_GLOW;
2195                 if (r_refdef.fogenabled)
2196                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2197                 if (rsurface.texture->colormapping)
2198                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2199                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2200                 {
2201                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2202                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2203
2204                         if (r_shadow_shadowmapsampler)
2205                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2206                         if (r_shadow_shadowmappcf > 1)
2207                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2208                         else if (r_shadow_shadowmappcf)
2209                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2210                 }
2211                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2212                         permutation |= SHADERPERMUTATION_REFLECTION;
2213                 if (rsurface.texture->reflectmasktexture)
2214                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2215                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2216                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2217         }
2218         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2219         {
2220                 if (r_glsl_offsetmapping.integer)
2221                 {
2222                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2223                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2224                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2225                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2226                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2227                         {
2228                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2229                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2230                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2231                         }
2232                 }
2233                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2234                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2235                 // directional model lighting
2236                 mode = SHADERMODE_LIGHTDIRECTION;
2237                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2238                         permutation |= SHADERPERMUTATION_GLOW;
2239                 permutation |= SHADERPERMUTATION_DIFFUSE;
2240                 if (specularscale > 0)
2241                         permutation |= SHADERPERMUTATION_SPECULAR;
2242                 if (r_refdef.fogenabled)
2243                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2244                 if (rsurface.texture->colormapping)
2245                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2246                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2247                 {
2248                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2249                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2250
2251                         if (r_shadow_shadowmapsampler)
2252                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2253                         if (r_shadow_shadowmappcf > 1)
2254                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2255                         else if (r_shadow_shadowmappcf)
2256                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2257                 }
2258                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2259                         permutation |= SHADERPERMUTATION_REFLECTION;
2260                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2261                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2262                 if (rsurface.texture->reflectmasktexture)
2263                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2264                 if (r_shadow_bouncegridtexture)
2265                 {
2266                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2267                         if (r_shadow_bouncegriddirectional)
2268                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2269                 }
2270                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2271                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2272         }
2273         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2274         {
2275                 if (r_glsl_offsetmapping.integer)
2276                 {
2277                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2278                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2279                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2280                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2281                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2282                         {
2283                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2284                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2285                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2286                         }
2287                 }
2288                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2289                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2290                 // ambient model lighting
2291                 mode = SHADERMODE_LIGHTDIRECTION;
2292                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2293                         permutation |= SHADERPERMUTATION_GLOW;
2294                 if (r_refdef.fogenabled)
2295                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2296                 if (rsurface.texture->colormapping)
2297                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2298                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2299                 {
2300                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2301                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2302
2303                         if (r_shadow_shadowmapsampler)
2304                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2305                         if (r_shadow_shadowmappcf > 1)
2306                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2307                         else if (r_shadow_shadowmappcf)
2308                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2309                 }
2310                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2311                         permutation |= SHADERPERMUTATION_REFLECTION;
2312                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2313                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2314                 if (rsurface.texture->reflectmasktexture)
2315                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2316                 if (r_shadow_bouncegridtexture)
2317                 {
2318                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2319                         if (r_shadow_bouncegriddirectional)
2320                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2321                 }
2322                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2323                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2324         }
2325         else
2326         {
2327                 if (r_glsl_offsetmapping.integer)
2328                 {
2329                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2330                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2331                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2332                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2333                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2334                         {
2335                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2336                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2337                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2338                         }
2339                 }
2340                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2341                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2342                 // lightmapped wall
2343                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2344                         permutation |= SHADERPERMUTATION_GLOW;
2345                 if (r_refdef.fogenabled)
2346                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2347                 if (rsurface.texture->colormapping)
2348                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2349                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2350                 {
2351                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2352                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2353
2354                         if (r_shadow_shadowmapsampler)
2355                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2356                         if (r_shadow_shadowmappcf > 1)
2357                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2358                         else if (r_shadow_shadowmappcf)
2359                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2360                 }
2361                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2362                         permutation |= SHADERPERMUTATION_REFLECTION;
2363                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2364                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2365                 if (rsurface.texture->reflectmasktexture)
2366                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2367                 if (FAKELIGHT_ENABLED)
2368                 {
2369                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2370                         mode = SHADERMODE_FAKELIGHT;
2371                         permutation |= SHADERPERMUTATION_DIFFUSE;
2372                         if (specularscale > 0)
2373                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2374                 }
2375                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2376                 {
2377                         // deluxemapping (light direction texture)
2378                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2379                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2380                         else
2381                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2382                         permutation |= SHADERPERMUTATION_DIFFUSE;
2383                         if (specularscale > 0)
2384                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2385                 }
2386                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2387                 {
2388                         // fake deluxemapping (uniform light direction in tangentspace)
2389                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2390                         permutation |= SHADERPERMUTATION_DIFFUSE;
2391                         if (specularscale > 0)
2392                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2393                 }
2394                 else if (rsurface.uselightmaptexture)
2395                 {
2396                         // ordinary lightmapping (q1bsp, q3bsp)
2397                         mode = SHADERMODE_LIGHTMAP;
2398                 }
2399                 else
2400                 {
2401                         // ordinary vertex coloring (q3bsp)
2402                         mode = SHADERMODE_VERTEXCOLOR;
2403                 }
2404                 if (r_shadow_bouncegridtexture)
2405                 {
2406                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2407                         if (r_shadow_bouncegriddirectional)
2408                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2409                 }
2410                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2411                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2412         }
2413         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2414                 colormod = dummy_colormod;
2415         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2416                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2417         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2418                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2419         switch(vid.renderpath)
2420         {
2421         case RENDERPATH_D3D9:
2422 #ifdef SUPPORTD3D
2423                 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);
2424                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2425                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2426                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2427                 if (mode == SHADERMODE_LIGHTSOURCE)
2428                 {
2429                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2430                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2431                 }
2432                 else
2433                 {
2434                         if (mode == SHADERMODE_LIGHTDIRECTION)
2435                         {
2436                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2437                         }
2438                 }
2439                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2440                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2441                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2442                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2443                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2444
2445                 if (mode == SHADERMODE_LIGHTSOURCE)
2446                 {
2447                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2448                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2449                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2450                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2451                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2452
2453                         // additive passes are only darkened by fog, not tinted
2454                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2455                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2456                 }
2457                 else
2458                 {
2459                         if (mode == SHADERMODE_FLATCOLOR)
2460                         {
2461                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2462                         }
2463                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2464                         {
2465                                 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]);
2466                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2467                                 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);
2468                                 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);
2469                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2470                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2471                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2472                         }
2473                         else
2474                         {
2475                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2476                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[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] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * 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                         }
2481                         // additive passes are only darkened by fog, not tinted
2482                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2483                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2484                         else
2485                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2486                         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);
2487                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2488                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2489                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2490                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2491                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2492                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2493                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2494                         if (mode == SHADERMODE_WATER)
2495                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2496                 }
2497                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2498                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2499                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2500                 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));
2501                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2502                 if (rsurface.texture->pantstexture)
2503                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2504                 else
2505                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2506                 if (rsurface.texture->shirttexture)
2507                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2508                 else
2509                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2510                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2511                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2512                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2513                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2514                 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));
2515                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2516                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2517
2518                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2519                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2520                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2521                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2522                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2523                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2524                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2525                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2526                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2527                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2528                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2529                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2530                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2531                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2532                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2533                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2534                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2535                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2536                 {
2537                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2538                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2539                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2540                 }
2541                 else
2542                 {
2543                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2544                 }
2545 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2546 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2547                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2548                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2549                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2550                 {
2551                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2552                         if (rsurface.rtlight)
2553                         {
2554                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2555                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2556                         }
2557                 }
2558 #endif
2559                 break;
2560         case RENDERPATH_D3D10:
2561                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2562                 break;
2563         case RENDERPATH_D3D11:
2564                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2565                 break;
2566         case RENDERPATH_GL20:
2567         case RENDERPATH_GLES2:
2568                 if (!vid.useinterleavedarrays)
2569                 {
2570                         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);
2571                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2572                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2573                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2574                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2575                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2576                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2577                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2578                 }
2579                 else
2580                 {
2581                         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);
2582                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2583                 }
2584                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2585                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2586                 if (mode == SHADERMODE_LIGHTSOURCE)
2587                 {
2588                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2589                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2590                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2591                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2592                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2593                         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);
2594         
2595                         // additive passes are only darkened by fog, not tinted
2596                         if (r_glsl_permutation->loc_FogColor >= 0)
2597                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2598                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2599                 }
2600                 else
2601                 {
2602                         if (mode == SHADERMODE_FLATCOLOR)
2603                         {
2604                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2605                         }
2606                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2607                         {
2608                                 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]);
2609                                 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]);
2610                                 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);
2611                                 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);
2612                                 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);
2613                                 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]);
2614                                 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]);
2615                         }
2616                         else
2617                         {
2618                                 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]);
2619                                 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]);
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] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * 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                         }
2624                         // additive passes are only darkened by fog, not tinted
2625                         if (r_glsl_permutation->loc_FogColor >= 0)
2626                         {
2627                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2628                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2629                                 else
2630                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2631                         }
2632                         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);
2633                         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]);
2634                         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]);
2635                         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]);
2636                         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]);
2637                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2638                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2639                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2640                         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]);
2641                 }
2642                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2643                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2644                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2645                 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]);
2646                 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]);
2647
2648                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2649                 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));
2650                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2651                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2652                 {
2653                         if (rsurface.texture->pantstexture)
2654                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2655                         else
2656                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2657                 }
2658                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2659                 {
2660                         if (rsurface.texture->shirttexture)
2661                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2662                         else
2663                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2664                 }
2665                 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]);
2666                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2667                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2668                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2669                 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));
2670                 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]);
2671                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2672                 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);}
2673                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2674
2675                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2676                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2677                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2678                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2679                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2680                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2681                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2682                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2683                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2684                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2685                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2686                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2687                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2688                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2689                 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);
2690                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2691                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2692                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2693                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2694                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2695                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2696                 {
2697                         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);
2698                         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);
2699                         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);
2700                 }
2701                 else
2702                 {
2703                         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);
2704                 }
2705                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2706                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2707                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2708                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2709                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2710                 {
2711                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2712                         if (rsurface.rtlight)
2713                         {
2714                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2715                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2716                         }
2717                 }
2718                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2719                 CHECKGLERROR
2720                 break;
2721         case RENDERPATH_GL13:
2722         case RENDERPATH_GL11:
2723                 break;
2724         case RENDERPATH_SOFT:
2725                 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);
2726                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2727                 R_SetupShader_SetPermutationSoft(mode, permutation);
2728                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2729                 if (mode == SHADERMODE_LIGHTSOURCE)
2730                 {
2731                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2732                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2733                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2734                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2735                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2736                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2737         
2738                         // additive passes are only darkened by fog, not tinted
2739                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2740                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2741                 }
2742                 else
2743                 {
2744                         if (mode == SHADERMODE_FLATCOLOR)
2745                         {
2746                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2747                         }
2748                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2749                         {
2750                                 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]);
2751                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2752                                 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);
2753                                 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);
2754                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2755                                 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]);
2756                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2757                         }
2758                         else
2759                         {
2760                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2761                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[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] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * 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                         }
2766                         // additive passes are only darkened by fog, not tinted
2767                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2768                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2769                         else
2770                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2771                         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);
2772                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2773                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2774                         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]);
2775                         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]);
2776                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2777                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2778                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2779                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2780                 }
2781                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2782                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2783                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2784                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2785                 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]);
2786
2787                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2788                 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));
2789                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2790                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2791                 {
2792                         if (rsurface.texture->pantstexture)
2793                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2794                         else
2795                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2796                 }
2797                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2798                 {
2799                         if (rsurface.texture->shirttexture)
2800                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2801                         else
2802                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2803                 }
2804                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2805                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2806                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2807                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2808                 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));
2809                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2810                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2811
2812                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2813                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2814                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2815                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2816                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2817                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2818                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2819                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2820                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2821                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2822                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2823                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2824                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2825                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2826                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2827                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2828                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2829                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2830                 {
2831                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2832                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2833                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2834                 }
2835                 else
2836                 {
2837                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2838                 }
2839 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2840 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2841                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2842                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2843                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2844                 {
2845                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2846                         if (rsurface.rtlight)
2847                         {
2848                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2849                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2850                         }
2851                 }
2852                 break;
2853         }
2854 }
2855
2856 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2857 {
2858         // select a permutation of the lighting shader appropriate to this
2859         // combination of texture, entity, light source, and fogging, only use the
2860         // minimum features necessary to avoid wasting rendering time in the
2861         // fragment shader on features that are not being used
2862         unsigned int permutation = 0;
2863         unsigned int mode = 0;
2864         const float *lightcolorbase = rtlight->currentcolor;
2865         float ambientscale = rtlight->ambientscale;
2866         float diffusescale = rtlight->diffusescale;
2867         float specularscale = rtlight->specularscale;
2868         // this is the location of the light in view space
2869         vec3_t viewlightorigin;
2870         // this transforms from view space (camera) to light space (cubemap)
2871         matrix4x4_t viewtolight;
2872         matrix4x4_t lighttoview;
2873         float viewtolight16f[16];
2874         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2875         // light source
2876         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2877         if (rtlight->currentcubemap != r_texture_whitecube)
2878                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2879         if (diffusescale > 0)
2880                 permutation |= SHADERPERMUTATION_DIFFUSE;
2881         if (specularscale > 0)
2882                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2883         if (r_shadow_usingshadowmap2d)
2884         {
2885                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2886                 if (r_shadow_shadowmapvsdct)
2887                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2888
2889                 if (r_shadow_shadowmapsampler)
2890                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2891                 if (r_shadow_shadowmappcf > 1)
2892                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2893                 else if (r_shadow_shadowmappcf)
2894                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2895         }
2896         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2897         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2898         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2899         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2900         switch(vid.renderpath)
2901         {
2902         case RENDERPATH_D3D9:
2903 #ifdef SUPPORTD3D
2904                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2905                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2906                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2907                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2908                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2909                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2910                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2911                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2912                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2913                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2914                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2915
2916                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2917                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2918                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2919                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2920                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2921                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2922 #endif
2923                 break;
2924         case RENDERPATH_D3D10:
2925                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2926                 break;
2927         case RENDERPATH_D3D11:
2928                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2929                 break;
2930         case RENDERPATH_GL20:
2931         case RENDERPATH_GLES2:
2932                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2933                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2934                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2935                 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);
2936                 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);
2937                 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);
2938                 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]);
2939                 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]);
2940                 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));
2941                 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]);
2942                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2943
2944                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2945                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2946                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2947                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2948                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2949                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2950                 break;
2951         case RENDERPATH_GL13:
2952         case RENDERPATH_GL11:
2953                 break;
2954         case RENDERPATH_SOFT:
2955                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2956                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2957                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2958                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2959                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2960                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2961                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2962                 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]);
2963                 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));
2964                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2965                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2966
2967                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2968                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2969                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2970                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2971                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2972                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2973                 break;
2974         }
2975 }
2976
2977 #define SKINFRAME_HASH 1024
2978
2979 typedef struct
2980 {
2981         int loadsequence; // incremented each level change
2982         memexpandablearray_t array;
2983         skinframe_t *hash[SKINFRAME_HASH];
2984 }
2985 r_skinframe_t;
2986 r_skinframe_t r_skinframe;
2987
2988 void R_SkinFrame_PrepareForPurge(void)
2989 {
2990         r_skinframe.loadsequence++;
2991         // wrap it without hitting zero
2992         if (r_skinframe.loadsequence >= 200)
2993                 r_skinframe.loadsequence = 1;
2994 }
2995
2996 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2997 {
2998         if (!skinframe)
2999                 return;
3000         // mark the skinframe as used for the purging code
3001         skinframe->loadsequence = r_skinframe.loadsequence;
3002 }
3003
3004 void R_SkinFrame_Purge(void)
3005 {
3006         int i;
3007         skinframe_t *s;
3008         for (i = 0;i < SKINFRAME_HASH;i++)
3009         {
3010                 for (s = r_skinframe.hash[i];s;s = s->next)
3011                 {
3012                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3013                         {
3014                                 if (s->merged == s->base)
3015                                         s->merged = NULL;
3016                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3017                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3018                                 R_PurgeTexture(s->merged);s->merged = NULL;
3019                                 R_PurgeTexture(s->base  );s->base   = NULL;
3020                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3021                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3022                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3023                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3024                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3025                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3026                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3027                                 s->loadsequence = 0;
3028                         }
3029                 }
3030         }
3031 }
3032
3033 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3034         skinframe_t *item;
3035         char basename[MAX_QPATH];
3036
3037         Image_StripImageExtension(name, basename, sizeof(basename));
3038
3039         if( last == NULL ) {
3040                 int hashindex;
3041                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3042                 item = r_skinframe.hash[hashindex];
3043         } else {
3044                 item = last->next;
3045         }
3046
3047         // linearly search through the hash bucket
3048         for( ; item ; item = item->next ) {
3049                 if( !strcmp( item->basename, basename ) ) {
3050                         return item;
3051                 }
3052         }
3053         return NULL;
3054 }
3055
3056 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3057 {
3058         skinframe_t *item;
3059         int hashindex;
3060         char basename[MAX_QPATH];
3061
3062         Image_StripImageExtension(name, basename, sizeof(basename));
3063
3064         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3065         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3066                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3067                         break;
3068
3069         if (!item) {
3070                 rtexture_t *dyntexture;
3071                 // check whether its a dynamic texture
3072                 dyntexture = CL_GetDynTexture( basename );
3073                 if (!add && !dyntexture)
3074                         return NULL;
3075                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3076                 memset(item, 0, sizeof(*item));
3077                 strlcpy(item->basename, basename, sizeof(item->basename));
3078                 item->base = dyntexture; // either NULL or dyntexture handle
3079                 item->textureflags = textureflags;
3080                 item->comparewidth = comparewidth;
3081                 item->compareheight = compareheight;
3082                 item->comparecrc = comparecrc;
3083                 item->next = r_skinframe.hash[hashindex];
3084                 r_skinframe.hash[hashindex] = item;
3085         }
3086         else if( item->base == NULL )
3087         {
3088                 rtexture_t *dyntexture;
3089                 // check whether its a dynamic texture
3090                 // 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]
3091                 dyntexture = CL_GetDynTexture( basename );
3092                 item->base = dyntexture; // either NULL or dyntexture handle
3093         }
3094
3095         R_SkinFrame_MarkUsed(item);
3096         return item;
3097 }
3098
3099 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3100         { \
3101                 unsigned long long avgcolor[5], wsum; \
3102                 int pix, comp, w; \
3103                 avgcolor[0] = 0; \
3104                 avgcolor[1] = 0; \
3105                 avgcolor[2] = 0; \
3106                 avgcolor[3] = 0; \
3107                 avgcolor[4] = 0; \
3108                 wsum = 0; \
3109                 for(pix = 0; pix < cnt; ++pix) \
3110                 { \
3111                         w = 0; \
3112                         for(comp = 0; comp < 3; ++comp) \
3113                                 w += getpixel; \
3114                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3115                         { \
3116                                 ++wsum; \
3117                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3118                                 w = getpixel; \
3119                                 for(comp = 0; comp < 3; ++comp) \
3120                                         avgcolor[comp] += getpixel * w; \
3121                                 avgcolor[3] += w; \
3122                         } \
3123                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3124                         avgcolor[4] += getpixel; \
3125                 } \
3126                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3127                         avgcolor[3] = 1; \
3128                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3129                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3130                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3131                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3132         }
3133
3134 extern cvar_t gl_picmip;
3135 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3136 {
3137         int j;
3138         unsigned char *pixels;
3139         unsigned char *bumppixels;
3140         unsigned char *basepixels = NULL;
3141         int basepixels_width = 0;
3142         int basepixels_height = 0;
3143         skinframe_t *skinframe;
3144         rtexture_t *ddsbase = NULL;
3145         qboolean ddshasalpha = false;
3146         float ddsavgcolor[4];
3147         char basename[MAX_QPATH];
3148         int miplevel = R_PicmipForFlags(textureflags);
3149         int savemiplevel = miplevel;
3150         int mymiplevel;
3151
3152         if (cls.state == ca_dedicated)
3153                 return NULL;
3154
3155         // return an existing skinframe if already loaded
3156         // if loading of the first image fails, don't make a new skinframe as it
3157         // would cause all future lookups of this to be missing
3158         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3159         if (skinframe && skinframe->base)
3160                 return skinframe;
3161
3162         Image_StripImageExtension(name, basename, sizeof(basename));
3163
3164         // check for DDS texture file first
3165         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3166         {
3167                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3168                 if (basepixels == NULL)
3169                         return NULL;
3170         }
3171
3172         // FIXME handle miplevel
3173
3174         if (developer_loading.integer)
3175                 Con_Printf("loading skin \"%s\"\n", name);
3176
3177         // we've got some pixels to store, so really allocate this new texture now
3178         if (!skinframe)
3179                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3180         skinframe->stain = NULL;
3181         skinframe->merged = NULL;
3182         skinframe->base = NULL;
3183         skinframe->pants = NULL;
3184         skinframe->shirt = NULL;
3185         skinframe->nmap = NULL;
3186         skinframe->gloss = NULL;
3187         skinframe->glow = NULL;
3188         skinframe->fog = NULL;
3189         skinframe->reflect = NULL;
3190         skinframe->hasalpha = false;
3191
3192         if (ddsbase)
3193         {
3194                 skinframe->base = ddsbase;
3195                 skinframe->hasalpha = ddshasalpha;
3196                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3197                 if (r_loadfog && skinframe->hasalpha)
3198                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3199                 //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]);
3200         }
3201         else
3202         {
3203                 basepixels_width = image_width;
3204                 basepixels_height = image_height;
3205                 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);
3206                 if (textureflags & TEXF_ALPHA)
3207                 {
3208                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3209                         {
3210                                 if (basepixels[j] < 255)
3211                                 {
3212                                         skinframe->hasalpha = true;
3213                                         break;
3214                                 }
3215                         }
3216                         if (r_loadfog && skinframe->hasalpha)
3217                         {
3218                                 // has transparent pixels
3219                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3220                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3221                                 {
3222                                         pixels[j+0] = 255;
3223                                         pixels[j+1] = 255;
3224                                         pixels[j+2] = 255;
3225                                         pixels[j+3] = basepixels[j+3];
3226                                 }
3227                                 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);
3228                                 Mem_Free(pixels);
3229                         }
3230                 }
3231                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3232                 //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]);
3233                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3234                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3235                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3236                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3237         }
3238
3239         if (r_loaddds)
3240         {
3241                 mymiplevel = savemiplevel;
3242                 if (r_loadnormalmap)
3243                         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);
3244                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3245                 if (r_loadgloss)
3246                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3247                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3248                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3249                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3250         }
3251
3252         // _norm is the name used by tenebrae and has been adopted as standard
3253         if (r_loadnormalmap && skinframe->nmap == NULL)
3254         {
3255                 mymiplevel = savemiplevel;
3256                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3257                 {
3258                         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);
3259                         Mem_Free(pixels);
3260                         pixels = NULL;
3261                 }
3262                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3263                 {
3264                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3265                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3266                         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);
3267                         Mem_Free(pixels);
3268                         Mem_Free(bumppixels);
3269                 }
3270                 else if (r_shadow_bumpscale_basetexture.value > 0)
3271                 {
3272                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3273                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3274                         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);
3275                         Mem_Free(pixels);
3276                 }
3277                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3278                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3279         }
3280
3281         // _luma is supported only for tenebrae compatibility
3282         // _glow is the preferred name
3283         mymiplevel = savemiplevel;
3284         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))))
3285         {
3286                 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);
3287                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3288                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3289                 Mem_Free(pixels);pixels = NULL;
3290         }
3291
3292         mymiplevel = savemiplevel;
3293         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3294         {
3295                 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);
3296                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3297                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3298                 Mem_Free(pixels);
3299                 pixels = NULL;
3300         }
3301
3302         mymiplevel = savemiplevel;
3303         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3304         {
3305                 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);
3306                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3307                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3308                 Mem_Free(pixels);
3309                 pixels = NULL;
3310         }
3311
3312         mymiplevel = savemiplevel;
3313         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3314         {
3315                 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);
3316                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3317                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3318                 Mem_Free(pixels);
3319                 pixels = NULL;
3320         }
3321
3322         mymiplevel = savemiplevel;
3323         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3324         {
3325                 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);
3326                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3327                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3328                 Mem_Free(pixels);
3329                 pixels = NULL;
3330         }
3331
3332         if (basepixels)
3333                 Mem_Free(basepixels);
3334
3335         return skinframe;
3336 }
3337
3338 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3339 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3340 {
3341         int i;
3342         unsigned char *temp1, *temp2;
3343         skinframe_t *skinframe;
3344
3345         if (cls.state == ca_dedicated)
3346                 return NULL;
3347
3348         // if already loaded just return it, otherwise make a new skinframe
3349         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3350         if (skinframe && skinframe->base)
3351                 return skinframe;
3352
3353         skinframe->stain = NULL;
3354         skinframe->merged = NULL;
3355         skinframe->base = NULL;
3356         skinframe->pants = NULL;
3357         skinframe->shirt = NULL;
3358         skinframe->nmap = NULL;
3359         skinframe->gloss = NULL;
3360         skinframe->glow = NULL;
3361         skinframe->fog = NULL;
3362         skinframe->reflect = NULL;
3363         skinframe->hasalpha = false;
3364
3365         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3366         if (!skindata)
3367                 return NULL;
3368
3369         if (developer_loading.integer)
3370                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3371
3372         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3373         {
3374                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3375                 temp2 = temp1 + width * height * 4;
3376                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3377                 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);
3378                 Mem_Free(temp1);
3379         }
3380         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3381         if (textureflags & TEXF_ALPHA)
3382         {
3383                 for (i = 3;i < width * height * 4;i += 4)
3384                 {
3385                         if (skindata[i] < 255)
3386                         {
3387                                 skinframe->hasalpha = true;
3388                                 break;
3389                         }
3390                 }
3391                 if (r_loadfog && skinframe->hasalpha)
3392                 {
3393                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3394                         memcpy(fogpixels, skindata, width * height * 4);
3395                         for (i = 0;i < width * height * 4;i += 4)
3396                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3397                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3398                         Mem_Free(fogpixels);
3399                 }
3400         }
3401
3402         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3403         //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]);
3404
3405         return skinframe;
3406 }
3407
3408 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3409 {
3410         int i;
3411         int featuresmask;
3412         skinframe_t *skinframe;
3413
3414         if (cls.state == ca_dedicated)
3415                 return NULL;
3416
3417         // if already loaded just return it, otherwise make a new skinframe
3418         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3419         if (skinframe && skinframe->base)
3420                 return skinframe;
3421
3422         skinframe->stain = NULL;
3423         skinframe->merged = NULL;
3424         skinframe->base = NULL;
3425         skinframe->pants = NULL;
3426         skinframe->shirt = NULL;
3427         skinframe->nmap = NULL;
3428         skinframe->gloss = NULL;
3429         skinframe->glow = NULL;
3430         skinframe->fog = NULL;
3431         skinframe->reflect = NULL;
3432         skinframe->hasalpha = false;
3433
3434         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3435         if (!skindata)
3436                 return NULL;
3437
3438         if (developer_loading.integer)
3439                 Con_Printf("loading quake skin \"%s\"\n", name);
3440
3441         // 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)
3442         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3443         memcpy(skinframe->qpixels, skindata, width*height);
3444         skinframe->qwidth = width;
3445         skinframe->qheight = height;
3446
3447         featuresmask = 0;
3448         for (i = 0;i < width * height;i++)
3449                 featuresmask |= palette_featureflags[skindata[i]];
3450
3451         skinframe->hasalpha = false;
3452         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3453         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3454         skinframe->qgeneratemerged = true;
3455         skinframe->qgeneratebase = skinframe->qhascolormapping;
3456         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3457
3458         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3459         //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]);
3460
3461         return skinframe;
3462 }
3463
3464 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3465 {
3466         int width;
3467         int height;
3468         unsigned char *skindata;
3469
3470         if (!skinframe->qpixels)
3471                 return;
3472
3473         if (!skinframe->qhascolormapping)
3474                 colormapped = false;
3475
3476         if (colormapped)
3477         {
3478                 if (!skinframe->qgeneratebase)
3479                         return;
3480         }
3481         else
3482         {
3483                 if (!skinframe->qgeneratemerged)
3484                         return;
3485         }
3486
3487         width = skinframe->qwidth;
3488         height = skinframe->qheight;
3489         skindata = skinframe->qpixels;
3490
3491         if (skinframe->qgeneratenmap)
3492         {
3493                 unsigned char *temp1, *temp2;
3494                 skinframe->qgeneratenmap = false;
3495                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3496                 temp2 = temp1 + width * height * 4;
3497                 // use either a custom palette or the quake palette
3498                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3499                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3500                 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);
3501                 Mem_Free(temp1);
3502         }
3503
3504         if (skinframe->qgenerateglow)
3505         {
3506                 skinframe->qgenerateglow = false;
3507                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3508         }
3509
3510         if (colormapped)
3511         {
3512                 skinframe->qgeneratebase = false;
3513                 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);
3514                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3515                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3516         }
3517         else
3518         {
3519                 skinframe->qgeneratemerged = false;
3520                 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);
3521         }
3522
3523         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3524         {
3525                 Mem_Free(skinframe->qpixels);
3526                 skinframe->qpixels = NULL;
3527         }
3528 }
3529
3530 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)
3531 {
3532         int i;
3533         skinframe_t *skinframe;
3534
3535         if (cls.state == ca_dedicated)
3536                 return NULL;
3537
3538         // if already loaded just return it, otherwise make a new skinframe
3539         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3540         if (skinframe && skinframe->base)
3541                 return skinframe;
3542
3543         skinframe->stain = NULL;
3544         skinframe->merged = NULL;
3545         skinframe->base = NULL;
3546         skinframe->pants = NULL;
3547         skinframe->shirt = NULL;
3548         skinframe->nmap = NULL;
3549         skinframe->gloss = NULL;
3550         skinframe->glow = NULL;
3551         skinframe->fog = NULL;
3552         skinframe->reflect = NULL;
3553         skinframe->hasalpha = false;
3554
3555         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3556         if (!skindata)
3557                 return NULL;
3558
3559         if (developer_loading.integer)
3560                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3561
3562         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3563         if (textureflags & TEXF_ALPHA)
3564         {
3565                 for (i = 0;i < width * height;i++)
3566                 {
3567                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3568                         {
3569                                 skinframe->hasalpha = true;
3570                                 break;
3571                         }
3572                 }
3573                 if (r_loadfog && skinframe->hasalpha)
3574                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3575         }
3576
3577         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3578         //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]);
3579
3580         return skinframe;
3581 }
3582
3583 skinframe_t *R_SkinFrame_LoadMissing(void)
3584 {
3585         skinframe_t *skinframe;
3586
3587         if (cls.state == ca_dedicated)
3588                 return NULL;
3589
3590         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3591         skinframe->stain = NULL;
3592         skinframe->merged = NULL;
3593         skinframe->base = NULL;
3594         skinframe->pants = NULL;
3595         skinframe->shirt = NULL;
3596         skinframe->nmap = NULL;
3597         skinframe->gloss = NULL;
3598         skinframe->glow = NULL;
3599         skinframe->fog = NULL;
3600         skinframe->reflect = NULL;
3601         skinframe->hasalpha = false;
3602
3603         skinframe->avgcolor[0] = rand() / RAND_MAX;
3604         skinframe->avgcolor[1] = rand() / RAND_MAX;
3605         skinframe->avgcolor[2] = rand() / RAND_MAX;
3606         skinframe->avgcolor[3] = 1;
3607
3608         return skinframe;
3609 }
3610
3611 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3612 typedef struct suffixinfo_s
3613 {
3614         const char *suffix;
3615         qboolean flipx, flipy, flipdiagonal;
3616 }
3617 suffixinfo_t;
3618 static suffixinfo_t suffix[3][6] =
3619 {
3620         {
3621                 {"px",   false, false, false},
3622                 {"nx",   false, false, false},
3623                 {"py",   false, false, false},
3624                 {"ny",   false, false, false},
3625                 {"pz",   false, false, false},
3626                 {"nz",   false, false, false}
3627         },
3628         {
3629                 {"posx", false, false, false},
3630                 {"negx", false, false, false},
3631                 {"posy", false, false, false},
3632                 {"negy", false, false, false},
3633                 {"posz", false, false, false},
3634                 {"negz", false, false, false}
3635         },
3636         {
3637                 {"rt",    true, false,  true},
3638                 {"lf",   false,  true,  true},
3639                 {"ft",    true,  true, false},
3640                 {"bk",   false, false, false},
3641                 {"up",    true, false,  true},
3642                 {"dn",    true, false,  true}
3643         }
3644 };
3645
3646 static int componentorder[4] = {0, 1, 2, 3};
3647
3648 rtexture_t *R_LoadCubemap(const char *basename)
3649 {
3650         int i, j, cubemapsize;
3651         unsigned char *cubemappixels, *image_buffer;
3652         rtexture_t *cubemaptexture;
3653         char name[256];
3654         // must start 0 so the first loadimagepixels has no requested width/height
3655         cubemapsize = 0;
3656         cubemappixels = NULL;
3657         cubemaptexture = NULL;
3658         // keep trying different suffix groups (posx, px, rt) until one loads
3659         for (j = 0;j < 3 && !cubemappixels;j++)
3660         {
3661                 // load the 6 images in the suffix group
3662                 for (i = 0;i < 6;i++)
3663                 {
3664                         // generate an image name based on the base and and suffix
3665                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3666                         // load it
3667                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3668                         {
3669                                 // an image loaded, make sure width and height are equal
3670                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3671                                 {
3672                                         // if this is the first image to load successfully, allocate the cubemap memory
3673                                         if (!cubemappixels && image_width >= 1)
3674                                         {
3675                                                 cubemapsize = image_width;
3676                                                 // note this clears to black, so unavailable sides are black
3677                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3678                                         }
3679                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3680                                         if (cubemappixels)
3681                                                 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);
3682                                 }
3683                                 else
3684                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3685                                 // free the image
3686                                 Mem_Free(image_buffer);
3687                         }
3688                 }
3689         }
3690         // if a cubemap loaded, upload it
3691         if (cubemappixels)
3692         {
3693                 if (developer_loading.integer)
3694                         Con_Printf("loading cubemap \"%s\"\n", basename);
3695
3696                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3697                 Mem_Free(cubemappixels);
3698         }
3699         else
3700         {
3701                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3702                 if (developer_loading.integer)
3703                 {
3704                         Con_Printf("(tried tried images ");
3705                         for (j = 0;j < 3;j++)
3706                                 for (i = 0;i < 6;i++)
3707                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3708                         Con_Print(" and was unable to find any of them).\n");
3709                 }
3710         }
3711         return cubemaptexture;
3712 }
3713
3714 rtexture_t *R_GetCubemap(const char *basename)
3715 {
3716         int i;
3717         for (i = 0;i < r_texture_numcubemaps;i++)
3718                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3719                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3720         if (i >= MAX_CUBEMAPS)
3721                 return r_texture_whitecube;
3722         r_texture_numcubemaps++;
3723         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3724         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3725         return r_texture_cubemaps[i].texture;
3726 }
3727
3728 void R_FreeCubemaps(void)
3729 {
3730         int i;
3731         for (i = 0;i < r_texture_numcubemaps;i++)
3732         {
3733                 if (developer_loading.integer)
3734                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3735                 if (r_texture_cubemaps[i].texture)
3736                         R_FreeTexture(r_texture_cubemaps[i].texture);
3737         }
3738         r_texture_numcubemaps = 0;
3739 }
3740
3741 void R_Main_FreeViewCache(void)
3742 {
3743         if (r_refdef.viewcache.entityvisible)
3744                 Mem_Free(r_refdef.viewcache.entityvisible);
3745         if (r_refdef.viewcache.world_pvsbits)
3746                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3747         if (r_refdef.viewcache.world_leafvisible)
3748                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3749         if (r_refdef.viewcache.world_surfacevisible)
3750                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3751         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3752 }
3753
3754 void R_Main_ResizeViewCache(void)
3755 {
3756         int numentities = r_refdef.scene.numentities;
3757         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3758         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3759         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3760         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3761         if (r_refdef.viewcache.maxentities < numentities)
3762         {
3763                 r_refdef.viewcache.maxentities = numentities;
3764                 if (r_refdef.viewcache.entityvisible)
3765                         Mem_Free(r_refdef.viewcache.entityvisible);
3766                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3767         }
3768         if (r_refdef.viewcache.world_numclusters != numclusters)
3769         {
3770                 r_refdef.viewcache.world_numclusters = numclusters;
3771                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3772                 if (r_refdef.viewcache.world_pvsbits)
3773                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3774                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3775         }
3776         if (r_refdef.viewcache.world_numleafs != numleafs)
3777         {
3778                 r_refdef.viewcache.world_numleafs = numleafs;
3779                 if (r_refdef.viewcache.world_leafvisible)
3780                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3781                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3782         }
3783         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3784         {
3785                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3786                 if (r_refdef.viewcache.world_surfacevisible)
3787                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3788                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3789         }
3790 }
3791
3792 extern rtexture_t *loadingscreentexture;
3793 void gl_main_start(void)
3794 {
3795         loadingscreentexture = NULL;
3796         r_texture_blanknormalmap = NULL;
3797         r_texture_white = NULL;
3798         r_texture_grey128 = NULL;
3799         r_texture_black = NULL;
3800         r_texture_whitecube = NULL;
3801         r_texture_normalizationcube = NULL;
3802         r_texture_fogattenuation = NULL;
3803         r_texture_fogheighttexture = NULL;
3804         r_texture_gammaramps = NULL;
3805         r_texture_numcubemaps = 0;
3806
3807         r_loaddds = r_texture_dds_load.integer != 0;
3808         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3809
3810         switch(vid.renderpath)
3811         {
3812         case RENDERPATH_GL20:
3813         case RENDERPATH_D3D9:
3814         case RENDERPATH_D3D10:
3815         case RENDERPATH_D3D11:
3816         case RENDERPATH_SOFT:
3817                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3818                 Cvar_SetValueQuick(&gl_combine, 1);
3819                 Cvar_SetValueQuick(&r_glsl, 1);
3820                 r_loadnormalmap = true;
3821                 r_loadgloss = true;
3822                 r_loadfog = false;
3823                 break;
3824         case RENDERPATH_GL13:
3825                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3826                 Cvar_SetValueQuick(&gl_combine, 1);
3827                 Cvar_SetValueQuick(&r_glsl, 0);
3828                 r_loadnormalmap = false;
3829                 r_loadgloss = false;
3830                 r_loadfog = true;
3831                 break;
3832         case RENDERPATH_GL11:
3833                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3834                 Cvar_SetValueQuick(&gl_combine, 0);
3835                 Cvar_SetValueQuick(&r_glsl, 0);
3836                 r_loadnormalmap = false;
3837                 r_loadgloss = false;
3838                 r_loadfog = true;
3839                 break;
3840         case RENDERPATH_GLES2:
3841                 Cvar_SetValueQuick(&r_textureunits, 1);
3842                 Cvar_SetValueQuick(&gl_combine, 1);
3843                 Cvar_SetValueQuick(&r_glsl, 1);
3844                 r_loadnormalmap = true;
3845                 r_loadgloss = false;
3846                 r_loadfog = false;
3847                 break;
3848         }
3849
3850         R_AnimCache_Free();
3851         R_FrameData_Reset();
3852
3853         r_numqueries = 0;
3854         r_maxqueries = 0;
3855         memset(r_queries, 0, sizeof(r_queries));
3856
3857         r_qwskincache = NULL;
3858         r_qwskincache_size = 0;
3859
3860         // due to caching of texture_t references, the collision cache must be reset
3861         Collision_Cache_Reset(true);
3862
3863         // set up r_skinframe loading system for textures
3864         memset(&r_skinframe, 0, sizeof(r_skinframe));
3865         r_skinframe.loadsequence = 1;
3866         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3867
3868         r_main_texturepool = R_AllocTexturePool();
3869         R_BuildBlankTextures();
3870         R_BuildNoTexture();
3871         if (vid.support.arb_texture_cube_map)
3872         {
3873                 R_BuildWhiteCube();
3874                 R_BuildNormalizationCube();
3875         }
3876         r_texture_fogattenuation = NULL;
3877         r_texture_fogheighttexture = NULL;
3878         r_texture_gammaramps = NULL;
3879         //r_texture_fogintensity = NULL;
3880         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3881         memset(&r_waterstate, 0, sizeof(r_waterstate));
3882         r_glsl_permutation = NULL;
3883         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3884         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3885         glslshaderstring = NULL;
3886 #ifdef SUPPORTD3D
3887         r_hlsl_permutation = NULL;
3888         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3889         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3890 #endif
3891         hlslshaderstring = NULL;
3892         memset(&r_svbsp, 0, sizeof (r_svbsp));
3893
3894         r_refdef.fogmasktable_density = 0;
3895 }
3896
3897 void gl_main_shutdown(void)
3898 {
3899         R_AnimCache_Free();
3900         R_FrameData_Reset();
3901
3902         R_Main_FreeViewCache();
3903
3904         switch(vid.renderpath)
3905         {
3906         case RENDERPATH_GL11:
3907         case RENDERPATH_GL13:
3908         case RENDERPATH_GL20:
3909         case RENDERPATH_GLES2:
3910                 if (r_maxqueries)
3911                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3912                 break;
3913         case RENDERPATH_D3D9:
3914                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3915                 break;
3916         case RENDERPATH_D3D10:
3917                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3918                 break;
3919         case RENDERPATH_D3D11:
3920                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3921                 break;
3922         case RENDERPATH_SOFT:
3923                 break;
3924         }
3925
3926         r_numqueries = 0;
3927         r_maxqueries = 0;
3928         memset(r_queries, 0, sizeof(r_queries));
3929
3930         r_qwskincache = NULL;
3931         r_qwskincache_size = 0;
3932
3933         // clear out the r_skinframe state
3934         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3935         memset(&r_skinframe, 0, sizeof(r_skinframe));
3936
3937         if (r_svbsp.nodes)
3938                 Mem_Free(r_svbsp.nodes);
3939         memset(&r_svbsp, 0, sizeof (r_svbsp));
3940         R_FreeTexturePool(&r_main_texturepool);
3941         loadingscreentexture = NULL;
3942         r_texture_blanknormalmap = NULL;
3943         r_texture_white = NULL;
3944         r_texture_grey128 = NULL;
3945         r_texture_black = NULL;
3946         r_texture_whitecube = NULL;
3947         r_texture_normalizationcube = NULL;
3948         r_texture_fogattenuation = NULL;
3949         r_texture_fogheighttexture = NULL;
3950         r_texture_gammaramps = NULL;
3951         r_texture_numcubemaps = 0;
3952         //r_texture_fogintensity = NULL;
3953         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3954         memset(&r_waterstate, 0, sizeof(r_waterstate));
3955         R_GLSL_Restart_f();
3956
3957         r_glsl_permutation = NULL;
3958         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3959         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3960         glslshaderstring = NULL;
3961 #ifdef SUPPORTD3D
3962         r_hlsl_permutation = NULL;
3963         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3964         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3965 #endif
3966         hlslshaderstring = NULL;
3967 }
3968
3969 extern void CL_ParseEntityLump(char *entitystring);
3970 void gl_main_newmap(void)
3971 {
3972         // FIXME: move this code to client
3973         char *entities, entname[MAX_QPATH];
3974         if (r_qwskincache)
3975                 Mem_Free(r_qwskincache);
3976         r_qwskincache = NULL;
3977         r_qwskincache_size = 0;
3978         if (cl.worldmodel)
3979         {
3980                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3981                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3982                 {
3983                         CL_ParseEntityLump(entities);
3984                         Mem_Free(entities);
3985                         return;
3986                 }
3987                 if (cl.worldmodel->brush.entities)
3988                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3989         }
3990         R_Main_FreeViewCache();
3991
3992         R_FrameData_Reset();
3993 }
3994
3995 void GL_Main_Init(void)
3996 {
3997         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3998
3999         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4000         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4001         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4002         if (gamemode == GAME_NEHAHRA)
4003         {
4004                 Cvar_RegisterVariable (&gl_fogenable);
4005                 Cvar_RegisterVariable (&gl_fogdensity);
4006                 Cvar_RegisterVariable (&gl_fogred);
4007                 Cvar_RegisterVariable (&gl_foggreen);
4008                 Cvar_RegisterVariable (&gl_fogblue);
4009                 Cvar_RegisterVariable (&gl_fogstart);
4010                 Cvar_RegisterVariable (&gl_fogend);
4011                 Cvar_RegisterVariable (&gl_skyclip);
4012         }
4013         Cvar_RegisterVariable(&r_motionblur);
4014         Cvar_RegisterVariable(&r_motionblur_maxblur);
4015         Cvar_RegisterVariable(&r_motionblur_bmin);
4016         Cvar_RegisterVariable(&r_motionblur_vmin);
4017         Cvar_RegisterVariable(&r_motionblur_vmax);
4018         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4019         Cvar_RegisterVariable(&r_motionblur_randomize);
4020         Cvar_RegisterVariable(&r_damageblur);
4021         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4022         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4023         Cvar_RegisterVariable(&r_equalize_entities_by);
4024         Cvar_RegisterVariable(&r_equalize_entities_to);
4025         Cvar_RegisterVariable(&r_depthfirst);
4026         Cvar_RegisterVariable(&r_useinfinitefarclip);
4027         Cvar_RegisterVariable(&r_farclip_base);
4028         Cvar_RegisterVariable(&r_farclip_world);
4029         Cvar_RegisterVariable(&r_nearclip);
4030         Cvar_RegisterVariable(&r_showbboxes);
4031         Cvar_RegisterVariable(&r_showsurfaces);
4032         Cvar_RegisterVariable(&r_showtris);
4033         Cvar_RegisterVariable(&r_shownormals);
4034         Cvar_RegisterVariable(&r_showlighting);
4035         Cvar_RegisterVariable(&r_showshadowvolumes);
4036         Cvar_RegisterVariable(&r_showcollisionbrushes);
4037         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4038         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4039         Cvar_RegisterVariable(&r_showdisabledepthtest);
4040         Cvar_RegisterVariable(&r_drawportals);
4041         Cvar_RegisterVariable(&r_drawentities);
4042         Cvar_RegisterVariable(&r_draw2d);
4043         Cvar_RegisterVariable(&r_drawworld);
4044         Cvar_RegisterVariable(&r_cullentities_trace);
4045         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4046         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4047         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4048         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4049         Cvar_RegisterVariable(&r_drawviewmodel);
4050         Cvar_RegisterVariable(&r_drawexteriormodel);
4051         Cvar_RegisterVariable(&r_speeds);
4052         Cvar_RegisterVariable(&r_fullbrights);
4053         Cvar_RegisterVariable(&r_wateralpha);
4054         Cvar_RegisterVariable(&r_dynamic);
4055         Cvar_RegisterVariable(&r_fakelight);
4056         Cvar_RegisterVariable(&r_fakelight_intensity);
4057         Cvar_RegisterVariable(&r_fullbright);
4058         Cvar_RegisterVariable(&r_shadows);
4059         Cvar_RegisterVariable(&r_shadows_darken);
4060         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4061         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4062         Cvar_RegisterVariable(&r_shadows_throwdistance);
4063         Cvar_RegisterVariable(&r_shadows_throwdirection);
4064         Cvar_RegisterVariable(&r_shadows_focus);
4065         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4066         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4067         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4068         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4069         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4070         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4071         Cvar_RegisterVariable(&r_fog_exp2);
4072         Cvar_RegisterVariable(&r_drawfog);
4073         Cvar_RegisterVariable(&r_transparentdepthmasking);
4074         Cvar_RegisterVariable(&r_texture_dds_load);
4075         Cvar_RegisterVariable(&r_texture_dds_save);
4076         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4077         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4078         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4079         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4080         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4081         Cvar_RegisterVariable(&r_textureunits);
4082         Cvar_RegisterVariable(&gl_combine);
4083         Cvar_RegisterVariable(&r_glsl);
4084         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4085         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4086         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4087         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4088         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4089         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4090         Cvar_RegisterVariable(&r_glsl_postprocess);
4091         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4092         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4093         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4094         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4095         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4096         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4097         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4098         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4099
4100         Cvar_RegisterVariable(&r_water);
4101         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4102         Cvar_RegisterVariable(&r_water_clippingplanebias);
4103         Cvar_RegisterVariable(&r_water_refractdistort);
4104         Cvar_RegisterVariable(&r_water_reflectdistort);
4105         Cvar_RegisterVariable(&r_water_scissormode);
4106         Cvar_RegisterVariable(&r_lerpsprites);
4107         Cvar_RegisterVariable(&r_lerpmodels);
4108         Cvar_RegisterVariable(&r_lerplightstyles);
4109         Cvar_RegisterVariable(&r_waterscroll);
4110         Cvar_RegisterVariable(&r_bloom);
4111         Cvar_RegisterVariable(&r_bloom_colorscale);
4112         Cvar_RegisterVariable(&r_bloom_brighten);
4113         Cvar_RegisterVariable(&r_bloom_blur);
4114         Cvar_RegisterVariable(&r_bloom_resolution);
4115         Cvar_RegisterVariable(&r_bloom_colorexponent);
4116         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4117         Cvar_RegisterVariable(&r_hdr);
4118         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4119         Cvar_RegisterVariable(&r_hdr_glowintensity);
4120         Cvar_RegisterVariable(&r_hdr_range);
4121         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4122         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4123         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4124         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4125         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4126         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4127         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4128         Cvar_RegisterVariable(&developer_texturelogging);
4129         Cvar_RegisterVariable(&gl_lightmaps);
4130         Cvar_RegisterVariable(&r_test);
4131         Cvar_RegisterVariable(&r_glsl_saturation);
4132         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4133         Cvar_RegisterVariable(&r_framedatasize);
4134         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4135                 Cvar_SetValue("r_fullbrights", 0);
4136         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4137
4138         Cvar_RegisterVariable(&r_track_sprites);
4139         Cvar_RegisterVariable(&r_track_sprites_flags);
4140         Cvar_RegisterVariable(&r_track_sprites_scalew);
4141         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4142         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4143         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4144         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4145         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4146 }
4147
4148 extern void R_Textures_Init(void);
4149 extern void GL_Draw_Init(void);
4150 extern void GL_Main_Init(void);
4151 extern void R_Shadow_Init(void);
4152 extern void R_Sky_Init(void);
4153 extern void GL_Surf_Init(void);
4154 extern void R_Particles_Init(void);
4155 extern void R_Explosion_Init(void);
4156 extern void gl_backend_init(void);
4157 extern void Sbar_Init(void);
4158 extern void R_LightningBeams_Init(void);
4159 extern void Mod_RenderInit(void);
4160 extern void Font_Init(void);
4161
4162 void Render_Init(void)
4163 {
4164         gl_backend_init();
4165         R_Textures_Init();
4166         GL_Main_Init();
4167         Font_Init();
4168         GL_Draw_Init();
4169         R_Shadow_Init();
4170         R_Sky_Init();
4171         GL_Surf_Init();
4172         Sbar_Init();
4173         R_Particles_Init();
4174         R_Explosion_Init();
4175         R_LightningBeams_Init();
4176         Mod_RenderInit();
4177 }
4178
4179 /*
4180 ===============
4181 GL_Init
4182 ===============
4183 */
4184 extern char *ENGINE_EXTENSIONS;
4185 void GL_Init (void)
4186 {
4187         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4188         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4189         gl_version = (const char *)qglGetString(GL_VERSION);
4190         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4191
4192         if (!gl_extensions)
4193                 gl_extensions = "";
4194         if (!gl_platformextensions)
4195                 gl_platformextensions = "";
4196
4197         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4198         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4199         Con_Printf("GL_VERSION: %s\n", gl_version);
4200         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4201         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4202
4203         VID_CheckExtensions();
4204
4205         // LordHavoc: report supported extensions
4206         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4207
4208         // clear to black (loading plaque will be seen over this)
4209         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4210 }
4211
4212 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4213 {
4214         int i;
4215         mplane_t *p;
4216         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4217         {
4218                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4219                 if (i == 4)
4220                         continue;
4221                 p = r_refdef.view.frustum + i;
4222                 switch(p->signbits)
4223                 {
4224                 default:
4225                 case 0:
4226                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4227                                 return true;
4228                         break;
4229                 case 1:
4230                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4231                                 return true;
4232                         break;
4233                 case 2:
4234                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4235                                 return true;
4236                         break;
4237                 case 3:
4238                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4239                                 return true;
4240                         break;
4241                 case 4:
4242                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4243                                 return true;
4244                         break;
4245                 case 5:
4246                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4247                                 return true;
4248                         break;
4249                 case 6:
4250                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4251                                 return true;
4252                         break;
4253                 case 7:
4254                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4255                                 return true;
4256                         break;
4257                 }
4258         }
4259         return false;
4260 }
4261
4262 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4263 {
4264         int i;
4265         const mplane_t *p;
4266         for (i = 0;i < numplanes;i++)
4267         {
4268                 p = planes + i;
4269                 switch(p->signbits)
4270                 {
4271                 default:
4272                 case 0:
4273                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4274                                 return true;
4275                         break;
4276                 case 1:
4277                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4278                                 return true;
4279                         break;
4280                 case 2:
4281                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4282                                 return true;
4283                         break;
4284                 case 3:
4285                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4286                                 return true;
4287                         break;
4288                 case 4:
4289                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4290                                 return true;
4291                         break;
4292                 case 5:
4293                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4294                                 return true;
4295                         break;
4296                 case 6:
4297                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4298                                 return true;
4299                         break;
4300                 case 7:
4301                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4302                                 return true;
4303                         break;
4304                 }
4305         }
4306         return false;
4307 }
4308
4309 //==================================================================================
4310
4311 // LordHavoc: this stores temporary data used within the same frame
4312
4313 typedef struct r_framedata_mem_s
4314 {
4315         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4316         size_t size; // how much usable space
4317         size_t current; // how much space in use
4318         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4319         size_t wantedsize; // how much space was allocated
4320         unsigned char *data; // start of real data (16byte aligned)
4321 }
4322 r_framedata_mem_t;
4323
4324 static r_framedata_mem_t *r_framedata_mem;
4325
4326 void R_FrameData_Reset(void)
4327 {
4328         while (r_framedata_mem)
4329         {
4330                 r_framedata_mem_t *next = r_framedata_mem->purge;
4331                 Mem_Free(r_framedata_mem);
4332                 r_framedata_mem = next;
4333         }
4334 }
4335
4336 void R_FrameData_Resize(void)
4337 {
4338         size_t wantedsize;
4339         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4340         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4341         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4342         {
4343                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4344                 newmem->wantedsize = wantedsize;
4345                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4346                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4347                 newmem->current = 0;
4348                 newmem->mark = 0;
4349                 newmem->purge = r_framedata_mem;
4350                 r_framedata_mem = newmem;
4351         }
4352 }
4353
4354 void R_FrameData_NewFrame(void)
4355 {
4356         R_FrameData_Resize();
4357         if (!r_framedata_mem)
4358                 return;
4359         // if we ran out of space on the last frame, free the old memory now
4360         while (r_framedata_mem->purge)
4361         {
4362                 // repeatedly remove the second item in the list, leaving only head
4363                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4364                 Mem_Free(r_framedata_mem->purge);
4365                 r_framedata_mem->purge = next;
4366         }
4367         // reset the current mem pointer
4368         r_framedata_mem->current = 0;
4369         r_framedata_mem->mark = 0;
4370 }
4371
4372 void *R_FrameData_Alloc(size_t size)
4373 {
4374         void *data;
4375
4376         // align to 16 byte boundary - the data pointer is already aligned, so we
4377         // only need to ensure the size of every allocation is also aligned
4378         size = (size + 15) & ~15;
4379
4380         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4381         {
4382                 // emergency - we ran out of space, allocate more memory
4383                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4384                 R_FrameData_Resize();
4385         }
4386
4387         data = r_framedata_mem->data + r_framedata_mem->current;
4388         r_framedata_mem->current += size;
4389
4390         // count the usage for stats
4391         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4392         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4393
4394         return (void *)data;
4395 }
4396
4397 void *R_FrameData_Store(size_t size, void *data)
4398 {
4399         void *d = R_FrameData_Alloc(size);
4400         if (d && data)
4401                 memcpy(d, data, size);
4402         return d;
4403 }
4404
4405 void R_FrameData_SetMark(void)
4406 {
4407         if (!r_framedata_mem)
4408                 return;
4409         r_framedata_mem->mark = r_framedata_mem->current;
4410 }
4411
4412 void R_FrameData_ReturnToMark(void)
4413 {
4414         if (!r_framedata_mem)
4415                 return;
4416         r_framedata_mem->current = r_framedata_mem->mark;
4417 }
4418
4419 //==================================================================================
4420
4421 // LordHavoc: animcache originally written by Echon, rewritten since then
4422
4423 /**
4424  * Animation cache prevents re-generating mesh data for an animated model
4425  * multiple times in one frame for lighting, shadowing, reflections, etc.
4426  */
4427
4428 void R_AnimCache_Free(void)
4429 {
4430 }
4431
4432 void R_AnimCache_ClearCache(void)
4433 {
4434         int i;
4435         entity_render_t *ent;
4436
4437         for (i = 0;i < r_refdef.scene.numentities;i++)
4438         {
4439                 ent = r_refdef.scene.entities[i];
4440                 ent->animcache_vertex3f = NULL;
4441                 ent->animcache_normal3f = NULL;
4442                 ent->animcache_svector3f = NULL;
4443                 ent->animcache_tvector3f = NULL;
4444                 ent->animcache_vertexmesh = NULL;
4445                 ent->animcache_vertex3fbuffer = NULL;
4446                 ent->animcache_vertexmeshbuffer = NULL;
4447         }
4448 }
4449
4450 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4451 {
4452         int i;
4453
4454         // check if we need the meshbuffers
4455         if (!vid.useinterleavedarrays)
4456                 return;
4457
4458         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4459                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4460         // TODO: upload vertex3f buffer?
4461         if (ent->animcache_vertexmesh)
4462         {
4463                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4464                 for (i = 0;i < numvertices;i++)
4465                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4466                 if (ent->animcache_svector3f)
4467                         for (i = 0;i < numvertices;i++)
4468                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4469                 if (ent->animcache_tvector3f)
4470                         for (i = 0;i < numvertices;i++)
4471                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4472                 if (ent->animcache_normal3f)
4473                         for (i = 0;i < numvertices;i++)
4474                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4475                 // TODO: upload vertexmeshbuffer?
4476         }
4477 }
4478
4479 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4480 {
4481         dp_model_t *model = ent->model;
4482         int numvertices;
4483         // see if it's already cached this frame
4484         if (ent->animcache_vertex3f)
4485         {
4486                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4487                 if (wantnormals || wanttangents)
4488                 {
4489                         if (ent->animcache_normal3f)
4490                                 wantnormals = false;
4491                         if (ent->animcache_svector3f)
4492                                 wanttangents = false;
4493                         if (wantnormals || wanttangents)
4494                         {
4495                                 numvertices = model->surfmesh.num_vertices;
4496                                 if (wantnormals)
4497                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4498                                 if (wanttangents)
4499                                 {
4500                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4501                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4502                                 }
4503                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4504                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4505                         }
4506                 }
4507         }
4508         else
4509         {
4510                 // see if this ent is worth caching
4511                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4512                         return false;
4513                 // get some memory for this entity and generate mesh data
4514                 numvertices = model->surfmesh.num_vertices;
4515                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4516                 if (wantnormals)
4517                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4518                 if (wanttangents)
4519                 {
4520                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4521                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4522                 }
4523                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4524                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4525         }
4526         return true;
4527 }
4528
4529 void R_AnimCache_CacheVisibleEntities(void)
4530 {
4531         int i;
4532         qboolean wantnormals = true;
4533         qboolean wanttangents = !r_showsurfaces.integer;
4534
4535         switch(vid.renderpath)
4536         {
4537         case RENDERPATH_GL20:
4538         case RENDERPATH_D3D9:
4539         case RENDERPATH_D3D10:
4540         case RENDERPATH_D3D11:
4541         case RENDERPATH_GLES2:
4542                 break;
4543         case RENDERPATH_GL13:
4544         case RENDERPATH_GL11:
4545                 wanttangents = false;
4546                 break;
4547         case RENDERPATH_SOFT:
4548                 break;
4549         }
4550
4551         if (r_shownormals.integer)
4552                 wanttangents = wantnormals = true;
4553
4554         // TODO: thread this
4555         // NOTE: R_PrepareRTLights() also caches entities
4556
4557         for (i = 0;i < r_refdef.scene.numentities;i++)
4558                 if (r_refdef.viewcache.entityvisible[i])
4559                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4560 }
4561
4562 //==================================================================================
4563
4564 static void R_View_UpdateEntityLighting (void)
4565 {
4566         int i;
4567         entity_render_t *ent;
4568         vec3_t tempdiffusenormal, avg;
4569         vec_t f, fa, fd, fdd;
4570         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4571
4572         for (i = 0;i < r_refdef.scene.numentities;i++)
4573         {
4574                 ent = r_refdef.scene.entities[i];
4575
4576                 // skip unseen models
4577                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4578                         continue;
4579
4580                 // skip bsp models
4581                 if (ent->model && ent->model->brush.num_leafs)
4582                 {
4583                         // TODO: use modellight for r_ambient settings on world?
4584                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4585                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4586                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4587                         continue;
4588                 }
4589
4590                 // fetch the lighting from the worldmodel data
4591                 VectorClear(ent->modellight_ambient);
4592                 VectorClear(ent->modellight_diffuse);
4593                 VectorClear(tempdiffusenormal);
4594                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4595                 {
4596                         vec3_t org;
4597                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4598
4599                         // complete lightning for lit sprites
4600                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4601                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4602                         {
4603                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4604                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4605                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4606                         }
4607                         else
4608                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4609
4610                         if(ent->flags & RENDER_EQUALIZE)
4611                         {
4612                                 // first fix up ambient lighting...
4613                                 if(r_equalize_entities_minambient.value > 0)
4614                                 {
4615                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4616                                         if(fd > 0)
4617                                         {
4618                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4619                                                 if(fa < r_equalize_entities_minambient.value * fd)
4620                                                 {
4621                                                         // solve:
4622                                                         //   fa'/fd' = minambient
4623                                                         //   fa'+0.25*fd' = fa+0.25*fd
4624                                                         //   ...
4625                                                         //   fa' = fd' * minambient
4626                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4627                                                         //   ...
4628                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4629                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4630                                                         //   ...
4631                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4632                                                         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
4633                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4634                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4635                                                 }
4636                                         }
4637                                 }
4638
4639                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4640                                 {
4641                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4642                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4643                                         f = fa + 0.25 * fd;
4644                                         if(f > 0)
4645                                         {
4646                                                 // adjust brightness and saturation to target
4647                                                 avg[0] = avg[1] = avg[2] = fa / f;
4648                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4649                                                 avg[0] = avg[1] = avg[2] = fd / f;
4650                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4651                                         }
4652                                 }
4653                         }
4654                 }
4655                 else // highly rare
4656                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4657
4658                 // move the light direction into modelspace coordinates for lighting code
4659                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4660                 if(VectorLength2(ent->modellight_lightdir) == 0)
4661                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4662                 VectorNormalize(ent->modellight_lightdir);
4663         }
4664 }
4665
4666 #define MAX_LINEOFSIGHTTRACES 64
4667
4668 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4669 {
4670         int i;
4671         vec3_t boxmins, boxmaxs;
4672         vec3_t start;
4673         vec3_t end;
4674         dp_model_t *model = r_refdef.scene.worldmodel;
4675
4676         if (!model || !model->brush.TraceLineOfSight)
4677                 return true;
4678
4679         // expand the box a little
4680         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4681         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4682         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4683         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4684         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4685         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4686
4687         // return true if eye is inside enlarged box
4688         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4689                 return true;
4690
4691         // try center
4692         VectorCopy(eye, start);
4693         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4694         if (model->brush.TraceLineOfSight(model, start, end))
4695                 return true;
4696
4697         // try various random positions
4698         for (i = 0;i < numsamples;i++)
4699         {
4700                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4701                 if (model->brush.TraceLineOfSight(model, start, end))
4702                         return true;
4703         }
4704
4705         return false;
4706 }
4707
4708
4709 static void R_View_UpdateEntityVisible (void)
4710 {
4711         int i;
4712         int renderimask;
4713         int samples;
4714         entity_render_t *ent;
4715
4716         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4717                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4718                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4719                 :                                                          RENDER_EXTERIORMODEL;
4720         if (!r_drawviewmodel.integer)
4721                 renderimask |= RENDER_VIEWMODEL;
4722         if (!r_drawexteriormodel.integer)
4723                 renderimask |= RENDER_EXTERIORMODEL;
4724         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4725         {
4726                 // worldmodel can check visibility
4727                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4728                 for (i = 0;i < r_refdef.scene.numentities;i++)
4729                 {
4730                         ent = r_refdef.scene.entities[i];
4731                         if (!(ent->flags & renderimask))
4732                         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)))
4733                         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))
4734                                 r_refdef.viewcache.entityvisible[i] = true;
4735                 }
4736                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4737                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4738                 {
4739                         for (i = 0;i < r_refdef.scene.numentities;i++)
4740                         {
4741                                 ent = r_refdef.scene.entities[i];
4742                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4743                                 {
4744                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4745                                         if (samples < 0)
4746                                                 continue; // temp entities do pvs only
4747                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4748                                                 ent->last_trace_visibility = realtime;
4749                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4750                                                 r_refdef.viewcache.entityvisible[i] = 0;
4751                                 }
4752                         }
4753                 }
4754         }
4755         else
4756         {
4757                 // no worldmodel or it can't check visibility
4758                 for (i = 0;i < r_refdef.scene.numentities;i++)
4759                 {
4760                         ent = r_refdef.scene.entities[i];
4761                         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));
4762                 }
4763         }
4764 }
4765
4766 /// only used if skyrendermasked, and normally returns false
4767 int R_DrawBrushModelsSky (void)
4768 {
4769         int i, sky;
4770         entity_render_t *ent;
4771
4772         sky = false;
4773         for (i = 0;i < r_refdef.scene.numentities;i++)
4774         {
4775                 if (!r_refdef.viewcache.entityvisible[i])
4776                         continue;
4777                 ent = r_refdef.scene.entities[i];
4778                 if (!ent->model || !ent->model->DrawSky)
4779                         continue;
4780                 ent->model->DrawSky(ent);
4781                 sky = true;
4782         }
4783         return sky;
4784 }
4785
4786 static void R_DrawNoModel(entity_render_t *ent);
4787 static void R_DrawModels(void)
4788 {
4789         int i;
4790         entity_render_t *ent;
4791
4792         for (i = 0;i < r_refdef.scene.numentities;i++)
4793         {
4794                 if (!r_refdef.viewcache.entityvisible[i])
4795                         continue;
4796                 ent = r_refdef.scene.entities[i];
4797                 r_refdef.stats.entities++;
4798                 if (ent->model && ent->model->Draw != NULL)
4799                         ent->model->Draw(ent);
4800                 else
4801                         R_DrawNoModel(ent);
4802         }
4803 }
4804
4805 static void R_DrawModelsDepth(void)
4806 {
4807         int i;
4808         entity_render_t *ent;
4809
4810         for (i = 0;i < r_refdef.scene.numentities;i++)
4811         {
4812                 if (!r_refdef.viewcache.entityvisible[i])
4813                         continue;
4814                 ent = r_refdef.scene.entities[i];
4815                 if (ent->model && ent->model->DrawDepth != NULL)
4816                         ent->model->DrawDepth(ent);
4817         }
4818 }
4819
4820 static void R_DrawModelsDebug(void)
4821 {
4822         int i;
4823         entity_render_t *ent;
4824
4825         for (i = 0;i < r_refdef.scene.numentities;i++)
4826         {
4827                 if (!r_refdef.viewcache.entityvisible[i])
4828                         continue;
4829                 ent = r_refdef.scene.entities[i];
4830                 if (ent->model && ent->model->DrawDebug != NULL)
4831                         ent->model->DrawDebug(ent);
4832         }
4833 }
4834
4835 static void R_DrawModelsAddWaterPlanes(void)
4836 {
4837         int i;
4838         entity_render_t *ent;
4839
4840         for (i = 0;i < r_refdef.scene.numentities;i++)
4841         {
4842                 if (!r_refdef.viewcache.entityvisible[i])
4843                         continue;
4844                 ent = r_refdef.scene.entities[i];
4845                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4846                         ent->model->DrawAddWaterPlanes(ent);
4847         }
4848 }
4849
4850 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4851 {
4852         if (r_hdr_irisadaptation.integer)
4853         {
4854                 vec3_t ambient;
4855                 vec3_t diffuse;
4856                 vec3_t diffusenormal;
4857                 vec_t brightness;
4858                 vec_t goal;
4859                 vec_t adjust;
4860                 vec_t current;
4861                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4862                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4863                 brightness = max(0.0000001f, brightness);
4864                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4865                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4866                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4867                 current = r_hdr_irisadaptation_value.value;
4868                 if (current < goal)
4869                         current = min(current + adjust, goal);
4870                 else if (current > goal)
4871                         current = max(current - adjust, goal);
4872                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4873                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4874         }
4875         else if (r_hdr_irisadaptation_value.value != 1.0f)
4876                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4877 }
4878
4879 static void R_View_SetFrustum(const int *scissor)
4880 {
4881         int i;
4882         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4883         vec3_t forward, left, up, origin, v;
4884
4885         if(scissor)
4886         {
4887                 // flipped x coordinates (because x points left here)
4888                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4889                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4890
4891                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4892                 switch(vid.renderpath)
4893                 {
4894                         case RENDERPATH_D3D9:
4895                         case RENDERPATH_D3D10:
4896                         case RENDERPATH_D3D11:
4897                         case RENDERPATH_SOFT:
4898                                 // non-flipped y coordinates
4899                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4900                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4901                                 break;
4902                         case RENDERPATH_GL11:
4903                         case RENDERPATH_GL13:
4904                         case RENDERPATH_GL20:
4905                         case RENDERPATH_GLES2:
4906                                 // non-flipped y coordinates
4907                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4908                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4909                                 break;
4910                 }
4911         }
4912
4913         // we can't trust r_refdef.view.forward and friends in reflected scenes
4914         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4915
4916 #if 0
4917         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4918         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4919         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4920         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4921         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4922         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4923         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4924         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4925         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4926         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4927         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4928         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4929 #endif
4930
4931 #if 0
4932         zNear = r_refdef.nearclip;
4933         nudge = 1.0 - 1.0 / (1<<23);
4934         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4935         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4936         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4937         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4938         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4939         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4940         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4941         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4942 #endif
4943
4944
4945
4946 #if 0
4947         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4948         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4949         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4950         r_refdef.view.frustum[0].dist = m[15] - m[12];
4951
4952         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4953         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4954         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4955         r_refdef.view.frustum[1].dist = m[15] + m[12];
4956
4957         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4958         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4959         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4960         r_refdef.view.frustum[2].dist = m[15] - m[13];
4961
4962         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4963         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4964         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4965         r_refdef.view.frustum[3].dist = m[15] + m[13];
4966
4967         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4968         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4969         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4970         r_refdef.view.frustum[4].dist = m[15] - m[14];
4971
4972         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4973         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4974         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4975         r_refdef.view.frustum[5].dist = m[15] + m[14];
4976 #endif
4977
4978         if (r_refdef.view.useperspective)
4979         {
4980                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4981                 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]);
4982                 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]);
4983                 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]);
4984                 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]);
4985
4986                 // then the normals from the corners relative to origin
4987                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4988                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4989                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4990                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4991
4992                 // in a NORMAL view, forward cross left == up
4993                 // in a REFLECTED view, forward cross left == down
4994                 // so our cross products above need to be adjusted for a left handed coordinate system
4995                 CrossProduct(forward, left, v);
4996                 if(DotProduct(v, up) < 0)
4997                 {
4998                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4999                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5000                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5001                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5002                 }
5003
5004                 // Leaving those out was a mistake, those were in the old code, and they
5005                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5006                 // I couldn't reproduce it after adding those normalizations. --blub
5007                 VectorNormalize(r_refdef.view.frustum[0].normal);
5008                 VectorNormalize(r_refdef.view.frustum[1].normal);
5009                 VectorNormalize(r_refdef.view.frustum[2].normal);
5010                 VectorNormalize(r_refdef.view.frustum[3].normal);
5011
5012                 // make the corners absolute
5013                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5014                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5015                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5016                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5017
5018                 // one more normal
5019                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5020
5021                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5022                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5023                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5024                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5025                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5026         }
5027         else
5028         {
5029                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5030                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5031                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5032                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5033                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5034                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5035                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5036                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5037                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5038                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5039         }
5040         r_refdef.view.numfrustumplanes = 5;
5041
5042         if (r_refdef.view.useclipplane)
5043         {
5044                 r_refdef.view.numfrustumplanes = 6;
5045                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5046         }
5047
5048         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5049                 PlaneClassify(r_refdef.view.frustum + i);
5050
5051         // LordHavoc: note to all quake engine coders, Quake had a special case
5052         // for 90 degrees which assumed a square view (wrong), so I removed it,
5053         // Quake2 has it disabled as well.
5054
5055         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5056         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5057         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5058         //PlaneClassify(&frustum[0]);
5059
5060         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5061         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5062         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5063         //PlaneClassify(&frustum[1]);
5064
5065         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5066         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5067         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5068         //PlaneClassify(&frustum[2]);
5069
5070         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5071         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5072         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5073         //PlaneClassify(&frustum[3]);
5074
5075         // nearclip plane
5076         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5077         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5078         //PlaneClassify(&frustum[4]);
5079 }
5080
5081 void R_View_UpdateWithScissor(const int *myscissor)
5082 {
5083         R_Main_ResizeViewCache();
5084         R_View_SetFrustum(myscissor);
5085         R_View_WorldVisibility(r_refdef.view.useclipplane);
5086         R_View_UpdateEntityVisible();
5087         R_View_UpdateEntityLighting();
5088 }
5089
5090 void R_View_Update(void)
5091 {
5092         R_Main_ResizeViewCache();
5093         R_View_SetFrustum(NULL);
5094         R_View_WorldVisibility(r_refdef.view.useclipplane);
5095         R_View_UpdateEntityVisible();
5096         R_View_UpdateEntityLighting();
5097 }
5098
5099 void R_SetupView(qboolean allowwaterclippingplane)
5100 {
5101         const float *customclipplane = NULL;
5102         float plane[4];
5103         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5104         {
5105                 // LordHavoc: couldn't figure out how to make this approach the
5106                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5107                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5108                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5109                         dist = r_refdef.view.clipplane.dist;
5110                 plane[0] = r_refdef.view.clipplane.normal[0];
5111                 plane[1] = r_refdef.view.clipplane.normal[1];
5112                 plane[2] = r_refdef.view.clipplane.normal[2];
5113                 plane[3] = dist;
5114                 customclipplane = plane;
5115         }
5116
5117         if (!r_refdef.view.useperspective)
5118                 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);
5119         else if (vid.stencil && r_useinfinitefarclip.integer)
5120                 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);
5121         else
5122                 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);
5123         R_SetViewport(&r_refdef.view.viewport);
5124 }
5125
5126 void R_EntityMatrix(const matrix4x4_t *matrix)
5127 {
5128         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5129         {
5130                 gl_modelmatrixchanged = false;
5131                 gl_modelmatrix = *matrix;
5132                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5133                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5134                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5135                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5136                 CHECKGLERROR
5137                 switch(vid.renderpath)
5138                 {
5139                 case RENDERPATH_D3D9:
5140 #ifdef SUPPORTD3D
5141                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5142                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5143 #endif
5144                         break;
5145                 case RENDERPATH_D3D10:
5146                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5147                         break;
5148                 case RENDERPATH_D3D11:
5149                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5150                         break;
5151                 case RENDERPATH_GL13:
5152                 case RENDERPATH_GL11:
5153                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5154                         break;
5155                 case RENDERPATH_SOFT:
5156                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5157                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5158                         break;
5159                 case RENDERPATH_GL20:
5160                 case RENDERPATH_GLES2:
5161                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5162                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5163                         break;
5164                 }
5165         }
5166 }
5167
5168 void R_ResetViewRendering2D(void)
5169 {
5170         r_viewport_t viewport;
5171         DrawQ_Finish();
5172
5173         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5174         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);
5175         R_SetViewport(&viewport);
5176         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5177         GL_Color(1, 1, 1, 1);
5178         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5179         GL_BlendFunc(GL_ONE, GL_ZERO);
5180         GL_ScissorTest(false);
5181         GL_DepthMask(false);
5182         GL_DepthRange(0, 1);
5183         GL_DepthTest(false);
5184         GL_DepthFunc(GL_LEQUAL);
5185         R_EntityMatrix(&identitymatrix);
5186         R_Mesh_ResetTextureState();
5187         GL_PolygonOffset(0, 0);
5188         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5189         switch(vid.renderpath)
5190         {
5191         case RENDERPATH_GL11:
5192         case RENDERPATH_GL13:
5193         case RENDERPATH_GL20:
5194         case RENDERPATH_GLES2:
5195                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5196                 break;
5197         case RENDERPATH_D3D9:
5198         case RENDERPATH_D3D10:
5199         case RENDERPATH_D3D11:
5200         case RENDERPATH_SOFT:
5201                 break;
5202         }
5203         GL_CullFace(GL_NONE);
5204 }
5205
5206 void R_ResetViewRendering3D(void)
5207 {
5208         DrawQ_Finish();
5209
5210         R_SetupView(true);
5211         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5212         GL_Color(1, 1, 1, 1);
5213         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5214         GL_BlendFunc(GL_ONE, GL_ZERO);
5215         GL_ScissorTest(true);
5216         GL_DepthMask(true);
5217         GL_DepthRange(0, 1);
5218         GL_DepthTest(true);
5219         GL_DepthFunc(GL_LEQUAL);
5220         R_EntityMatrix(&identitymatrix);
5221         R_Mesh_ResetTextureState();
5222         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5223         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5224         switch(vid.renderpath)
5225         {
5226         case RENDERPATH_GL11:
5227         case RENDERPATH_GL13:
5228         case RENDERPATH_GL20:
5229         case RENDERPATH_GLES2:
5230                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5231                 break;
5232         case RENDERPATH_D3D9:
5233         case RENDERPATH_D3D10:
5234         case RENDERPATH_D3D11:
5235         case RENDERPATH_SOFT:
5236                 break;
5237         }
5238         GL_CullFace(r_refdef.view.cullface_back);
5239 }
5240
5241 /*
5242 ================
5243 R_RenderView_UpdateViewVectors
5244 ================
5245 */
5246 static void R_RenderView_UpdateViewVectors(void)
5247 {
5248         // break apart the view matrix into vectors for various purposes
5249         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5250         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5251         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5252         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5253         // make an inverted copy of the view matrix for tracking sprites
5254         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5255 }
5256
5257 void R_RenderScene(void);
5258 void R_RenderWaterPlanes(void);
5259
5260 static void R_Water_StartFrame(void)
5261 {
5262         int i;
5263         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5264         r_waterstate_waterplane_t *p;
5265
5266         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5267                 return;
5268
5269         switch(vid.renderpath)
5270         {
5271         case RENDERPATH_GL20:
5272         case RENDERPATH_D3D9:
5273         case RENDERPATH_D3D10:
5274         case RENDERPATH_D3D11:
5275         case RENDERPATH_SOFT:
5276         case RENDERPATH_GLES2:
5277                 break;
5278         case RENDERPATH_GL13:
5279         case RENDERPATH_GL11:
5280                 return;
5281         }
5282
5283         // set waterwidth and waterheight to the water resolution that will be
5284         // used (often less than the screen resolution for faster rendering)
5285         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5286         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5287
5288         // calculate desired texture sizes
5289         // can't use water if the card does not support the texture size
5290         if (!r_water.integer || r_showsurfaces.integer)
5291                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5292         else if (vid.support.arb_texture_non_power_of_two)
5293         {
5294                 texturewidth = waterwidth;
5295                 textureheight = waterheight;
5296                 camerawidth = waterwidth;
5297                 cameraheight = waterheight;
5298         }
5299         else
5300         {
5301                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5302                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5303                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5304                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5305         }
5306
5307         // allocate textures as needed
5308         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5309         {
5310                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5311                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5312                 {
5313                         if (p->texture_refraction)
5314                                 R_FreeTexture(p->texture_refraction);
5315                         p->texture_refraction = NULL;
5316                         if (p->texture_reflection)
5317                                 R_FreeTexture(p->texture_reflection);
5318                         p->texture_reflection = NULL;
5319                         if (p->texture_camera)
5320                                 R_FreeTexture(p->texture_camera);
5321                         p->texture_camera = NULL;
5322                 }
5323                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5324                 r_waterstate.texturewidth = texturewidth;
5325                 r_waterstate.textureheight = textureheight;
5326                 r_waterstate.camerawidth = camerawidth;
5327                 r_waterstate.cameraheight = cameraheight;
5328         }
5329
5330         if (r_waterstate.texturewidth)
5331         {
5332                 r_waterstate.enabled = true;
5333
5334                 // when doing a reduced render (HDR) we want to use a smaller area
5335                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5336                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5337
5338                 // set up variables that will be used in shader setup
5339                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5340                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5341                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5342                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5343         }
5344
5345         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5346         r_waterstate.numwaterplanes = 0;
5347 }
5348
5349 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5350 {
5351         int triangleindex, planeindex;
5352         const int *e;
5353         vec3_t vert[3];
5354         vec3_t normal;
5355         vec3_t center;
5356         mplane_t plane;
5357         r_waterstate_waterplane_t *p;
5358         texture_t *t = R_GetCurrentTexture(surface->texture);
5359
5360         // just use the first triangle with a valid normal for any decisions
5361         VectorClear(normal);
5362         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5363         {
5364                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5365                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5366                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5367                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5368                 if (VectorLength2(normal) >= 0.001)
5369                         break;
5370         }
5371
5372         VectorCopy(normal, plane.normal);
5373         VectorNormalize(plane.normal);
5374         plane.dist = DotProduct(vert[0], plane.normal);
5375         PlaneClassify(&plane);
5376         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5377         {
5378                 // skip backfaces (except if nocullface is set)
5379                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5380                         return;
5381                 VectorNegate(plane.normal, plane.normal);
5382                 plane.dist *= -1;
5383                 PlaneClassify(&plane);
5384         }
5385
5386
5387         // find a matching plane if there is one
5388         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5389                 if(p->camera_entity == t->camera_entity)
5390                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5391                                 break;
5392         if (planeindex >= r_waterstate.maxwaterplanes)
5393                 return; // nothing we can do, out of planes
5394
5395         // if this triangle does not fit any known plane rendered this frame, add one
5396         if (planeindex >= r_waterstate.numwaterplanes)
5397         {
5398                 // store the new plane
5399                 r_waterstate.numwaterplanes++;
5400                 p->plane = plane;
5401                 // clear materialflags and pvs
5402                 p->materialflags = 0;
5403                 p->pvsvalid = false;
5404                 p->camera_entity = t->camera_entity;
5405                 VectorCopy(surface->mins, p->mins);
5406                 VectorCopy(surface->maxs, p->maxs);
5407         }
5408         else
5409         {
5410                 // merge mins/maxs
5411                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5412                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5413                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5414                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5415                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5416                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5417         }
5418         // merge this surface's materialflags into the waterplane
5419         p->materialflags |= t->currentmaterialflags;
5420         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5421         {
5422                 // merge this surface's PVS into the waterplane
5423                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5424                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5425                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5426                 {
5427                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5428                         p->pvsvalid = true;
5429                 }
5430         }
5431 }
5432
5433 static void R_Water_ProcessPlanes(void)
5434 {
5435         int myscissor[4];
5436         r_refdef_view_t originalview;
5437         r_refdef_view_t myview;
5438         int planeindex;
5439         r_waterstate_waterplane_t *p;
5440         vec3_t visorigin;
5441
5442         originalview = r_refdef.view;
5443
5444         // make sure enough textures are allocated
5445         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5446         {
5447                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5448                 {
5449                         if (!p->texture_refraction)
5450                                 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);
5451                         if (!p->texture_refraction)
5452                                 goto error;
5453                 }
5454                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5455                 {
5456                         if (!p->texture_camera)
5457                                 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);
5458                         if (!p->texture_camera)
5459                                 goto error;
5460                 }
5461
5462                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5463                 {
5464                         if (!p->texture_reflection)
5465                                 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);
5466                         if (!p->texture_reflection)
5467                                 goto error;
5468                 }
5469         }
5470
5471         // render views
5472         r_refdef.view = originalview;
5473         r_refdef.view.showdebug = false;
5474         r_refdef.view.width = r_waterstate.waterwidth;
5475         r_refdef.view.height = r_waterstate.waterheight;
5476         r_refdef.view.useclipplane = true;
5477         myview = r_refdef.view;
5478         r_waterstate.renderingscene = true;
5479         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5480         {
5481                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5482                 {
5483                         r_refdef.view = myview;
5484                         if(r_water_scissormode.integer)
5485                         {
5486                                 R_SetupView(true);
5487                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5488                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5489                         }
5490
5491                         // render reflected scene and copy into texture
5492                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5493                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5494                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5495                         r_refdef.view.clipplane = p->plane;
5496
5497                         // reverse the cullface settings for this render
5498                         r_refdef.view.cullface_front = GL_FRONT;
5499                         r_refdef.view.cullface_back = GL_BACK;
5500                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5501                         {
5502                                 r_refdef.view.usecustompvs = true;
5503                                 if (p->pvsvalid)
5504                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5505                                 else
5506                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5507                         }
5508
5509                         R_ResetViewRendering3D();
5510                         R_ClearScreen(r_refdef.fogenabled);
5511                         if(r_water_scissormode.integer & 2)
5512                                 R_View_UpdateWithScissor(myscissor);
5513                         else
5514                                 R_View_Update();
5515                         if(r_water_scissormode.integer & 1)
5516                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5517                         R_RenderScene();
5518
5519                         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);
5520                 }
5521
5522                 // render the normal view scene and copy into texture
5523                 // (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)
5524                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5525                 {
5526                         r_refdef.view = myview;
5527                         if(r_water_scissormode.integer)
5528                         {
5529                                 R_SetupView(true);
5530                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5531                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5532                         }
5533
5534                         r_waterstate.renderingrefraction = true;
5535
5536                         r_refdef.view.clipplane = p->plane;
5537                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5538                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5539
5540                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5541                         {
5542                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5543                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5544                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5545                                 R_RenderView_UpdateViewVectors();
5546                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5547                                 {
5548                                         r_refdef.view.usecustompvs = true;
5549                                         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);
5550                                 }
5551                         }
5552
5553                         PlaneClassify(&r_refdef.view.clipplane);
5554
5555                         R_ResetViewRendering3D();
5556                         R_ClearScreen(r_refdef.fogenabled);
5557                         if(r_water_scissormode.integer & 2)
5558                                 R_View_UpdateWithScissor(myscissor);
5559                         else
5560                                 R_View_Update();
5561                         if(r_water_scissormode.integer & 1)
5562                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5563                         R_RenderScene();
5564
5565                         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);
5566                         r_waterstate.renderingrefraction = false;
5567                 }
5568                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5569                 {
5570                         r_refdef.view = myview;
5571
5572                         r_refdef.view.clipplane = p->plane;
5573                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5574                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5575
5576                         r_refdef.view.width = r_waterstate.camerawidth;
5577                         r_refdef.view.height = r_waterstate.cameraheight;
5578                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5579                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5580
5581                         if(p->camera_entity)
5582                         {
5583                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5584                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5585                         }
5586
5587                         // note: all of the view is used for displaying... so
5588                         // there is no use in scissoring
5589
5590                         // reverse the cullface settings for this render
5591                         r_refdef.view.cullface_front = GL_FRONT;
5592                         r_refdef.view.cullface_back = GL_BACK;
5593                         // also reverse the view matrix
5594                         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
5595                         R_RenderView_UpdateViewVectors();
5596                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5597                         {
5598                                 r_refdef.view.usecustompvs = true;
5599                                 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);
5600                         }
5601                         
5602                         // camera needs no clipplane
5603                         r_refdef.view.useclipplane = false;
5604
5605                         PlaneClassify(&r_refdef.view.clipplane);
5606
5607                         R_ResetViewRendering3D();
5608                         R_ClearScreen(r_refdef.fogenabled);
5609                         R_View_Update();
5610                         R_RenderScene();
5611
5612                         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);
5613                         r_waterstate.renderingrefraction = false;
5614                 }
5615
5616         }
5617         r_waterstate.renderingscene = false;
5618         r_refdef.view = originalview;
5619         R_ResetViewRendering3D();
5620         R_ClearScreen(r_refdef.fogenabled);
5621         R_View_Update();
5622         return;
5623 error:
5624         r_refdef.view = originalview;
5625         r_waterstate.renderingscene = false;
5626         Cvar_SetValueQuick(&r_water, 0);
5627         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5628         return;
5629 }
5630
5631 void R_Bloom_StartFrame(void)
5632 {
5633         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5634
5635         switch(vid.renderpath)
5636         {
5637         case RENDERPATH_GL20:
5638         case RENDERPATH_D3D9:
5639         case RENDERPATH_D3D10:
5640         case RENDERPATH_D3D11:
5641         case RENDERPATH_SOFT:
5642         case RENDERPATH_GLES2:
5643                 break;
5644         case RENDERPATH_GL13:
5645         case RENDERPATH_GL11:
5646                 return;
5647         }
5648
5649         // set bloomwidth and bloomheight to the bloom resolution that will be
5650         // used (often less than the screen resolution for faster rendering)
5651         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5652         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5653         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5654         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5655         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5656
5657         // calculate desired texture sizes
5658         if (vid.support.arb_texture_non_power_of_two)
5659         {
5660                 screentexturewidth = r_refdef.view.width;
5661                 screentextureheight = r_refdef.view.height;
5662                 bloomtexturewidth = r_bloomstate.bloomwidth;
5663                 bloomtextureheight = r_bloomstate.bloomheight;
5664         }
5665         else
5666         {
5667                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5668                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5669                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5670                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5671         }
5672
5673         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))
5674         {
5675                 Cvar_SetValueQuick(&r_hdr, 0);
5676                 Cvar_SetValueQuick(&r_bloom, 0);
5677                 Cvar_SetValueQuick(&r_motionblur, 0);
5678                 Cvar_SetValueQuick(&r_damageblur, 0);
5679         }
5680
5681         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)))
5682                 screentexturewidth = screentextureheight = 0;
5683         if (!r_hdr.integer && !r_bloom.integer)
5684                 bloomtexturewidth = bloomtextureheight = 0;
5685
5686         // allocate textures as needed
5687         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5688         {
5689                 if (r_bloomstate.texture_screen)
5690                         R_FreeTexture(r_bloomstate.texture_screen);
5691                 r_bloomstate.texture_screen = NULL;
5692                 r_bloomstate.screentexturewidth = screentexturewidth;
5693                 r_bloomstate.screentextureheight = screentextureheight;
5694                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5695                         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);
5696         }
5697         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5698         {
5699                 if (r_bloomstate.texture_bloom)
5700                         R_FreeTexture(r_bloomstate.texture_bloom);
5701                 r_bloomstate.texture_bloom = NULL;
5702                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5703                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5704                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5705                         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);
5706         }
5707
5708         // when doing a reduced render (HDR) we want to use a smaller area
5709         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5710         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5711         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5712         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5713         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5714
5715         // set up a texcoord array for the full resolution screen image
5716         // (we have to keep this around to copy back during final render)
5717         r_bloomstate.screentexcoord2f[0] = 0;
5718         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5719         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5720         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5721         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5722         r_bloomstate.screentexcoord2f[5] = 0;
5723         r_bloomstate.screentexcoord2f[6] = 0;
5724         r_bloomstate.screentexcoord2f[7] = 0;
5725
5726         // set up a texcoord array for the reduced resolution bloom image
5727         // (which will be additive blended over the screen image)
5728         r_bloomstate.bloomtexcoord2f[0] = 0;
5729         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5730         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5731         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5732         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5733         r_bloomstate.bloomtexcoord2f[5] = 0;
5734         r_bloomstate.bloomtexcoord2f[6] = 0;
5735         r_bloomstate.bloomtexcoord2f[7] = 0;
5736
5737         switch(vid.renderpath)
5738         {
5739         case RENDERPATH_GL11:
5740         case RENDERPATH_GL13:
5741         case RENDERPATH_GL20:
5742         case RENDERPATH_SOFT:
5743         case RENDERPATH_GLES2:
5744                 break;
5745         case RENDERPATH_D3D9:
5746         case RENDERPATH_D3D10:
5747         case RENDERPATH_D3D11:
5748                 {
5749                         int i;
5750                         for (i = 0;i < 4;i++)
5751                         {
5752                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5753                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5754                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5755                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5756                         }
5757                 }
5758                 break;
5759         }
5760
5761         if (r_hdr.integer || r_bloom.integer)
5762         {
5763                 r_bloomstate.enabled = true;
5764                 r_bloomstate.hdr = r_hdr.integer != 0;
5765         }
5766
5767         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);
5768 }
5769
5770 void R_Bloom_CopyBloomTexture(float colorscale)
5771 {
5772         r_refdef.stats.bloom++;
5773
5774         // scale down screen texture to the bloom texture size
5775         CHECKGLERROR
5776         R_SetViewport(&r_bloomstate.viewport);
5777         GL_BlendFunc(GL_ONE, GL_ZERO);
5778         GL_Color(colorscale, colorscale, colorscale, 1);
5779         // 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...
5780         switch(vid.renderpath)
5781         {
5782         case RENDERPATH_GL11:
5783         case RENDERPATH_GL13:
5784         case RENDERPATH_GL20:
5785         case RENDERPATH_SOFT:
5786         case RENDERPATH_GLES2:
5787                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5788                 break;
5789         case RENDERPATH_D3D9:
5790         case RENDERPATH_D3D10:
5791         case RENDERPATH_D3D11:
5792                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5793                 break;
5794         }
5795         // TODO: do boxfilter scale-down in shader?
5796         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5797         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5798         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5799
5800         // we now have a bloom image in the framebuffer
5801         // copy it into the bloom image texture for later processing
5802         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);
5803         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5804 }
5805
5806 void R_Bloom_CopyHDRTexture(void)
5807 {
5808         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);
5809         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5810 }
5811
5812 void R_Bloom_MakeTexture(void)
5813 {
5814         int x, range, dir;
5815         float xoffset, yoffset, r, brighten;
5816
5817         r_refdef.stats.bloom++;
5818
5819         R_ResetViewRendering2D();
5820
5821         // we have a bloom image in the framebuffer
5822         CHECKGLERROR
5823         R_SetViewport(&r_bloomstate.viewport);
5824
5825         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5826         {
5827                 x *= 2;
5828                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5829                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5830                 GL_Color(r,r,r,1);
5831                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5832                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5833                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5834                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5835
5836                 // copy the vertically blurred bloom view to a texture
5837                 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);
5838                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5839         }
5840
5841         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5842         brighten = r_bloom_brighten.value;
5843         if (r_hdr.integer)
5844                 brighten *= r_hdr_range.value;
5845         brighten = sqrt(brighten);
5846         if(range >= 1)
5847                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5848         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5849
5850         for (dir = 0;dir < 2;dir++)
5851         {
5852                 // blend on at multiple vertical offsets to achieve a vertical blur
5853                 // TODO: do offset blends using GLSL
5854                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5855                 GL_BlendFunc(GL_ONE, GL_ZERO);
5856                 for (x = -range;x <= range;x++)
5857                 {
5858                         if (!dir){xoffset = 0;yoffset = x;}
5859                         else {xoffset = x;yoffset = 0;}
5860                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5861                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5862                         // compute a texcoord array with the specified x and y offset
5863                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5864                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5865                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5866                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5867                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5868                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5869                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5870                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5871                         // this r value looks like a 'dot' particle, fading sharply to
5872                         // black at the edges
5873                         // (probably not realistic but looks good enough)
5874                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5875                         //r = brighten/(range*2+1);
5876                         r = brighten / (range * 2 + 1);
5877                         if(range >= 1)
5878                                 r *= (1 - x*x/(float)(range*range));
5879                         GL_Color(r, r, r, 1);
5880                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5881                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5882                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5883                         GL_BlendFunc(GL_ONE, GL_ONE);
5884                 }
5885
5886                 // copy the vertically blurred bloom view to a texture
5887                 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);
5888                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5889         }
5890 }
5891
5892 void R_HDR_RenderBloomTexture(void)
5893 {
5894         int oldwidth, oldheight;
5895         float oldcolorscale;
5896         qboolean oldwaterstate;
5897
5898         oldwaterstate = r_waterstate.enabled;
5899         oldcolorscale = r_refdef.view.colorscale;
5900         oldwidth = r_refdef.view.width;
5901         oldheight = r_refdef.view.height;
5902         r_refdef.view.width = r_bloomstate.bloomwidth;
5903         r_refdef.view.height = r_bloomstate.bloomheight;
5904
5905         if(r_hdr.integer < 2)
5906                 r_waterstate.enabled = false;
5907
5908         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5909         // TODO: add exposure compensation features
5910         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5911
5912         r_refdef.view.showdebug = false;
5913         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5914
5915         R_ResetViewRendering3D();
5916
5917         R_ClearScreen(r_refdef.fogenabled);
5918         if (r_timereport_active)
5919                 R_TimeReport("HDRclear");
5920
5921         R_View_Update();
5922         if (r_timereport_active)
5923                 R_TimeReport("visibility");
5924
5925         // only do secondary renders with HDR if r_hdr is 2 or higher
5926         r_waterstate.numwaterplanes = 0;
5927         if (r_waterstate.enabled)
5928                 R_RenderWaterPlanes();
5929
5930         r_refdef.view.showdebug = true;
5931         R_RenderScene();
5932         r_waterstate.numwaterplanes = 0;
5933
5934         R_ResetViewRendering2D();
5935
5936         R_Bloom_CopyHDRTexture();
5937         R_Bloom_MakeTexture();
5938
5939         // restore the view settings
5940         r_waterstate.enabled = oldwaterstate;
5941         r_refdef.view.width = oldwidth;
5942         r_refdef.view.height = oldheight;
5943         r_refdef.view.colorscale = oldcolorscale;
5944
5945         R_ResetViewRendering3D();
5946
5947         R_ClearScreen(r_refdef.fogenabled);
5948         if (r_timereport_active)
5949                 R_TimeReport("viewclear");
5950 }
5951
5952 static void R_BlendView(void)
5953 {
5954         unsigned int permutation;
5955         float uservecs[4][4];
5956
5957         switch (vid.renderpath)
5958         {
5959         case RENDERPATH_GL20:
5960         case RENDERPATH_D3D9:
5961         case RENDERPATH_D3D10:
5962         case RENDERPATH_D3D11:
5963         case RENDERPATH_SOFT:
5964         case RENDERPATH_GLES2:
5965                 permutation =
5966                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5967                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5968                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5969                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5970                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5971
5972                 if (r_bloomstate.texture_screen)
5973                 {
5974                         // make sure the buffer is available
5975                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5976
5977                         R_ResetViewRendering2D();
5978
5979                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5980                         {
5981                                 // declare variables
5982                                 float speed;
5983                                 static float avgspeed;
5984
5985                                 speed = VectorLength(cl.movement_velocity);
5986
5987                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5988                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5989
5990                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5991                                 speed = bound(0, speed, 1);
5992                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5993
5994                                 // calculate values into a standard alpha
5995                                 cl.motionbluralpha = 1 - exp(-
5996                                                 (
5997                                                  (r_motionblur.value * speed / 80)
5998                                                  +
5999                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6000                                                 )
6001                                                 /
6002                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6003                                            );
6004
6005                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6006                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6007                                 // apply the blur
6008                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6009                                 {
6010                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6011                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6012                                         switch(vid.renderpath)
6013                                         {
6014                                         case RENDERPATH_GL11:
6015                                         case RENDERPATH_GL13:
6016                                         case RENDERPATH_GL20:
6017                                         case RENDERPATH_SOFT:
6018                                         case RENDERPATH_GLES2:
6019                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6020                                                 break;
6021                                         case RENDERPATH_D3D9:
6022                                         case RENDERPATH_D3D10:
6023                                         case RENDERPATH_D3D11:
6024                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6025                                                 break;
6026                                         }
6027                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6028                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6029                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6030                                 }
6031                         }
6032
6033                         // copy view into the screen texture
6034                         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);
6035                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6036                 }
6037                 else if (!r_bloomstate.texture_bloom)
6038                 {
6039                         // we may still have to do view tint...
6040                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6041                         {
6042                                 // apply a color tint to the whole view
6043                                 R_ResetViewRendering2D();
6044                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6045                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6046                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6047                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6048                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6049                         }
6050                         break; // no screen processing, no bloom, skip it
6051                 }
6052
6053                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6054                 {
6055                         // render simple bloom effect
6056                         // copy the screen and shrink it and darken it for the bloom process
6057                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6058                         // make the bloom texture
6059                         R_Bloom_MakeTexture();
6060                 }
6061
6062 #if _MSC_VER >= 1400
6063 #define sscanf sscanf_s
6064 #endif
6065                 memset(uservecs, 0, sizeof(uservecs));
6066                 if (r_glsl_postprocess_uservec1_enable.integer)
6067                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6068                 if (r_glsl_postprocess_uservec2_enable.integer)
6069                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6070                 if (r_glsl_postprocess_uservec3_enable.integer)
6071                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6072                 if (r_glsl_postprocess_uservec4_enable.integer)
6073                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6074
6075                 R_ResetViewRendering2D();
6076                 GL_Color(1, 1, 1, 1);
6077                 GL_BlendFunc(GL_ONE, GL_ZERO);
6078
6079                 switch(vid.renderpath)
6080                 {
6081                 case RENDERPATH_GL20:
6082                 case RENDERPATH_GLES2:
6083                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6084                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6085                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6086                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6087                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6088                         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]);
6089                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6090                         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]);
6091                         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]);
6092                         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]);
6093                         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]);
6094                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6095                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6096                         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);
6097                         break;
6098                 case RENDERPATH_D3D9:
6099 #ifdef SUPPORTD3D
6100                         // 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...
6101                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6102                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6103                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6104                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6105                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6106                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6107                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6108                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6109                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6110                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6111                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6112                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6113                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6114                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6115 #endif
6116                         break;
6117                 case RENDERPATH_D3D10:
6118                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6119                         break;
6120                 case RENDERPATH_D3D11:
6121                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6122                         break;
6123                 case RENDERPATH_SOFT:
6124                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6125                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6126                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6127                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6128                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6129                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6130                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6131                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6132                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6133                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6134                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6135                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6136                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6137                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6138                         break;
6139                 default:
6140                         break;
6141                 }
6142                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6143                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6144                 break;
6145         case RENDERPATH_GL13:
6146         case RENDERPATH_GL11:
6147                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6148                 {
6149                         // apply a color tint to the whole view
6150                         R_ResetViewRendering2D();
6151                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6152                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6153                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6154                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6155                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6156                 }
6157                 break;
6158         }
6159 }
6160
6161 matrix4x4_t r_waterscrollmatrix;
6162
6163 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6164 {
6165         if (r_refdef.fog_density)
6166         {
6167                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6168                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6169                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6170
6171                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6172                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6173                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6174                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6175
6176                 {
6177                         vec3_t fogvec;
6178                         VectorCopy(r_refdef.fogcolor, fogvec);
6179                         //   color.rgb *= ContrastBoost * SceneBrightness;
6180                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6181                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6182                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6183                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6184                 }
6185         }
6186 }
6187
6188 void R_UpdateVariables(void)
6189 {
6190         R_Textures_Frame();
6191
6192         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6193
6194         r_refdef.farclip = r_farclip_base.value;
6195         if (r_refdef.scene.worldmodel)
6196                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6197         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6198
6199         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6200                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6201         r_refdef.polygonfactor = 0;
6202         r_refdef.polygonoffset = 0;
6203         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6204         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6205
6206         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6207         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6208         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6209         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6210         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6211         if (FAKELIGHT_ENABLED)
6212         {
6213                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6214         }
6215         if (r_showsurfaces.integer)
6216         {
6217                 r_refdef.scene.rtworld = false;
6218                 r_refdef.scene.rtworldshadows = false;
6219                 r_refdef.scene.rtdlight = false;
6220                 r_refdef.scene.rtdlightshadows = false;
6221                 r_refdef.lightmapintensity = 0;
6222         }
6223
6224         if (gamemode == GAME_NEHAHRA)
6225         {
6226                 if (gl_fogenable.integer)
6227                 {
6228                         r_refdef.oldgl_fogenable = true;
6229                         r_refdef.fog_density = gl_fogdensity.value;
6230                         r_refdef.fog_red = gl_fogred.value;
6231                         r_refdef.fog_green = gl_foggreen.value;
6232                         r_refdef.fog_blue = gl_fogblue.value;
6233                         r_refdef.fog_alpha = 1;
6234                         r_refdef.fog_start = 0;
6235                         r_refdef.fog_end = gl_skyclip.value;
6236                         r_refdef.fog_height = 1<<30;
6237                         r_refdef.fog_fadedepth = 128;
6238                 }
6239                 else if (r_refdef.oldgl_fogenable)
6240                 {
6241                         r_refdef.oldgl_fogenable = false;
6242                         r_refdef.fog_density = 0;
6243                         r_refdef.fog_red = 0;
6244                         r_refdef.fog_green = 0;
6245                         r_refdef.fog_blue = 0;
6246                         r_refdef.fog_alpha = 0;
6247                         r_refdef.fog_start = 0;
6248                         r_refdef.fog_end = 0;
6249                         r_refdef.fog_height = 1<<30;
6250                         r_refdef.fog_fadedepth = 128;
6251                 }
6252         }
6253
6254         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6255         r_refdef.fog_start = max(0, r_refdef.fog_start);
6256         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6257
6258         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6259
6260         if (r_refdef.fog_density && r_drawfog.integer)
6261         {
6262                 r_refdef.fogenabled = true;
6263                 // this is the point where the fog reaches 0.9986 alpha, which we
6264                 // consider a good enough cutoff point for the texture
6265                 // (0.9986 * 256 == 255.6)
6266                 if (r_fog_exp2.integer)
6267                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6268                 else
6269                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6270                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6271                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6272                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6273                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6274                         R_BuildFogHeightTexture();
6275                 // fog color was already set
6276                 // update the fog texture
6277                 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)
6278                         R_BuildFogTexture();
6279                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6280                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6281         }
6282         else
6283                 r_refdef.fogenabled = false;
6284
6285         switch(vid.renderpath)
6286         {
6287         case RENDERPATH_GL20:
6288         case RENDERPATH_D3D9:
6289         case RENDERPATH_D3D10:
6290         case RENDERPATH_D3D11:
6291         case RENDERPATH_SOFT:
6292         case RENDERPATH_GLES2:
6293                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6294                 {
6295                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6296                         {
6297                                 // build GLSL gamma texture
6298 #define RAMPWIDTH 256
6299                                 unsigned short ramp[RAMPWIDTH * 3];
6300                                 unsigned char rampbgr[RAMPWIDTH][4];
6301                                 int i;
6302
6303                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6304
6305                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6306                                 for(i = 0; i < RAMPWIDTH; ++i)
6307                                 {
6308                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6309                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6310                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6311                                         rampbgr[i][3] = 0;
6312                                 }
6313                                 if (r_texture_gammaramps)
6314                                 {
6315                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6316                                 }
6317                                 else
6318                                 {
6319                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6320                                 }
6321                         }
6322                 }
6323                 else
6324                 {
6325                         // remove GLSL gamma texture
6326                 }
6327                 break;
6328         case RENDERPATH_GL13:
6329         case RENDERPATH_GL11:
6330                 break;
6331         }
6332 }
6333
6334 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6335 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6336 /*
6337 ================
6338 R_SelectScene
6339 ================
6340 */
6341 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6342         if( scenetype != r_currentscenetype ) {
6343                 // store the old scenetype
6344                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6345                 r_currentscenetype = scenetype;
6346                 // move in the new scene
6347                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6348         }
6349 }
6350
6351 /*
6352 ================
6353 R_GetScenePointer
6354 ================
6355 */
6356 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6357 {
6358         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6359         if( scenetype == r_currentscenetype ) {
6360                 return &r_refdef.scene;
6361         } else {
6362                 return &r_scenes_store[ scenetype ];
6363         }
6364 }
6365
6366 /*
6367 ================
6368 R_RenderView
6369 ================
6370 */
6371 int dpsoftrast_test;
6372 void R_RenderView(void)
6373 {
6374         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6375
6376         dpsoftrast_test = r_test.integer;
6377
6378         if (r_timereport_active)
6379                 R_TimeReport("start");
6380         r_textureframe++; // used only by R_GetCurrentTexture
6381         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6382
6383         if(R_CompileShader_CheckStaticParms())
6384                 R_GLSL_Restart_f();
6385
6386         if (!r_drawentities.integer)
6387                 r_refdef.scene.numentities = 0;
6388
6389         R_AnimCache_ClearCache();
6390         R_FrameData_NewFrame();
6391
6392         /* adjust for stereo display */
6393         if(R_Stereo_Active())
6394         {
6395                 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);
6396                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6397         }
6398
6399         if (r_refdef.view.isoverlay)
6400         {
6401                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6402                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6403                 R_TimeReport("depthclear");
6404
6405                 r_refdef.view.showdebug = false;
6406
6407                 r_waterstate.enabled = false;
6408                 r_waterstate.numwaterplanes = 0;
6409
6410                 R_RenderScene();
6411
6412                 r_refdef.view.matrix = originalmatrix;
6413
6414                 CHECKGLERROR
6415                 return;
6416         }
6417
6418         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6419         {
6420                 r_refdef.view.matrix = originalmatrix;
6421                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6422         }
6423
6424         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6425
6426         R_RenderView_UpdateViewVectors();
6427
6428         R_Shadow_UpdateWorldLightSelection();
6429
6430         R_Bloom_StartFrame();
6431         R_Water_StartFrame();
6432
6433         CHECKGLERROR
6434         if (r_timereport_active)
6435                 R_TimeReport("viewsetup");
6436
6437         R_ResetViewRendering3D();
6438
6439         if (r_refdef.view.clear || r_refdef.fogenabled)
6440         {
6441                 R_ClearScreen(r_refdef.fogenabled);
6442                 if (r_timereport_active)
6443                         R_TimeReport("viewclear");
6444         }
6445         r_refdef.view.clear = true;
6446
6447         // this produces a bloom texture to be used in R_BlendView() later
6448         if (r_hdr.integer && r_bloomstate.bloomwidth)
6449         {
6450                 R_HDR_RenderBloomTexture();
6451                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6452                 r_textureframe++; // used only by R_GetCurrentTexture
6453         }
6454
6455         r_refdef.view.showdebug = true;
6456
6457         R_View_Update();
6458         if (r_timereport_active)
6459                 R_TimeReport("visibility");
6460
6461         r_waterstate.numwaterplanes = 0;
6462         if (r_waterstate.enabled)
6463                 R_RenderWaterPlanes();
6464
6465         R_RenderScene();
6466         r_waterstate.numwaterplanes = 0;
6467
6468         R_BlendView();
6469         if (r_timereport_active)
6470                 R_TimeReport("blendview");
6471
6472         GL_Scissor(0, 0, vid.width, vid.height);
6473         GL_ScissorTest(false);
6474
6475         r_refdef.view.matrix = originalmatrix;
6476
6477         CHECKGLERROR
6478 }
6479
6480 void R_RenderWaterPlanes(void)
6481 {
6482         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6483         {
6484                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6485                 if (r_timereport_active)
6486                         R_TimeReport("waterworld");
6487         }
6488
6489         // don't let sound skip if going slow
6490         if (r_refdef.scene.extraupdate)
6491                 S_ExtraUpdate ();
6492
6493         R_DrawModelsAddWaterPlanes();
6494         if (r_timereport_active)
6495                 R_TimeReport("watermodels");
6496
6497         if (r_waterstate.numwaterplanes)
6498         {
6499                 R_Water_ProcessPlanes();
6500                 if (r_timereport_active)
6501                         R_TimeReport("waterscenes");
6502         }
6503 }
6504
6505 extern void R_DrawLightningBeams (void);
6506 extern void VM_CL_AddPolygonsToMeshQueue (void);
6507 extern void R_DrawPortals (void);
6508 extern cvar_t cl_locs_show;
6509 static void R_DrawLocs(void);
6510 static void R_DrawEntityBBoxes(void);
6511 static void R_DrawModelDecals(void);
6512 extern void R_DrawModelShadows(void);
6513 extern void R_DrawModelShadowMaps(void);
6514 extern cvar_t cl_decals_newsystem;
6515 extern qboolean r_shadow_usingdeferredprepass;
6516 void R_RenderScene(void)
6517 {
6518         qboolean shadowmapping = false;
6519
6520         if (r_timereport_active)
6521                 R_TimeReport("beginscene");
6522
6523         r_refdef.stats.renders++;
6524
6525         R_UpdateFogColor();
6526
6527         // don't let sound skip if going slow
6528         if (r_refdef.scene.extraupdate)
6529                 S_ExtraUpdate ();
6530
6531         R_MeshQueue_BeginScene();
6532
6533         R_SkyStartFrame();
6534
6535         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);
6536
6537         if (r_timereport_active)
6538                 R_TimeReport("skystartframe");
6539
6540         if (cl.csqc_vidvars.drawworld)
6541         {
6542                 // don't let sound skip if going slow
6543                 if (r_refdef.scene.extraupdate)
6544                         S_ExtraUpdate ();
6545
6546                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6547                 {
6548                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6549                         if (r_timereport_active)
6550                                 R_TimeReport("worldsky");
6551                 }
6552
6553                 if (R_DrawBrushModelsSky() && r_timereport_active)
6554                         R_TimeReport("bmodelsky");
6555
6556                 if (skyrendermasked && skyrenderlater)
6557                 {
6558                         // we have to force off the water clipping plane while rendering sky
6559                         R_SetupView(false);
6560                         R_Sky();
6561                         R_SetupView(true);
6562                         if (r_timereport_active)
6563                                 R_TimeReport("sky");
6564                 }
6565         }
6566
6567         R_AnimCache_CacheVisibleEntities();
6568         if (r_timereport_active)
6569                 R_TimeReport("animation");
6570
6571         R_Shadow_PrepareLights();
6572         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6573                 R_Shadow_PrepareModelShadows();
6574         if (r_timereport_active)
6575                 R_TimeReport("preparelights");
6576
6577         if (R_Shadow_ShadowMappingEnabled())
6578                 shadowmapping = true;
6579
6580         if (r_shadow_usingdeferredprepass)
6581                 R_Shadow_DrawPrepass();
6582
6583         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6584         {
6585                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6586                 if (r_timereport_active)
6587                         R_TimeReport("worlddepth");
6588         }
6589         if (r_depthfirst.integer >= 2)
6590         {
6591                 R_DrawModelsDepth();
6592                 if (r_timereport_active)
6593                         R_TimeReport("modeldepth");
6594         }
6595
6596         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6597         {
6598                 R_DrawModelShadowMaps();
6599                 R_ResetViewRendering3D();
6600                 // don't let sound skip if going slow
6601                 if (r_refdef.scene.extraupdate)
6602                         S_ExtraUpdate ();
6603         }
6604
6605         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6606         {
6607                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6608                 if (r_timereport_active)
6609                         R_TimeReport("world");
6610         }
6611
6612         // don't let sound skip if going slow
6613         if (r_refdef.scene.extraupdate)
6614                 S_ExtraUpdate ();
6615
6616         R_DrawModels();
6617         if (r_timereport_active)
6618                 R_TimeReport("models");
6619
6620         // don't let sound skip if going slow
6621         if (r_refdef.scene.extraupdate)
6622                 S_ExtraUpdate ();
6623
6624         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6625         {
6626                 R_DrawModelShadows();
6627                 R_ResetViewRendering3D();
6628                 // don't let sound skip if going slow
6629                 if (r_refdef.scene.extraupdate)
6630                         S_ExtraUpdate ();
6631         }
6632
6633         if (!r_shadow_usingdeferredprepass)
6634         {
6635                 R_Shadow_DrawLights();
6636                 if (r_timereport_active)
6637                         R_TimeReport("rtlights");
6638         }
6639
6640         // don't let sound skip if going slow
6641         if (r_refdef.scene.extraupdate)
6642                 S_ExtraUpdate ();
6643
6644         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6645         {
6646                 R_DrawModelShadows();
6647                 R_ResetViewRendering3D();
6648                 // don't let sound skip if going slow
6649                 if (r_refdef.scene.extraupdate)
6650                         S_ExtraUpdate ();
6651         }
6652
6653         if (cl.csqc_vidvars.drawworld)
6654         {
6655                 if (cl_decals_newsystem.integer)
6656                 {
6657                         R_DrawModelDecals();
6658                         if (r_timereport_active)
6659                                 R_TimeReport("modeldecals");
6660                 }
6661                 else
6662                 {
6663                         R_DrawDecals();
6664                         if (r_timereport_active)
6665                                 R_TimeReport("decals");
6666                 }
6667
6668                 R_DrawParticles();
6669                 if (r_timereport_active)
6670                         R_TimeReport("particles");
6671
6672                 R_DrawExplosions();
6673                 if (r_timereport_active)
6674                         R_TimeReport("explosions");
6675
6676                 R_DrawLightningBeams();
6677                 if (r_timereport_active)
6678                         R_TimeReport("lightning");
6679         }
6680
6681         VM_CL_AddPolygonsToMeshQueue();
6682
6683         if (r_refdef.view.showdebug)
6684         {
6685                 if (cl_locs_show.integer)
6686                 {
6687                         R_DrawLocs();
6688                         if (r_timereport_active)
6689                                 R_TimeReport("showlocs");
6690                 }
6691
6692                 if (r_drawportals.integer)
6693                 {
6694                         R_DrawPortals();
6695                         if (r_timereport_active)
6696                                 R_TimeReport("portals");
6697                 }
6698
6699                 if (r_showbboxes.value > 0)
6700                 {
6701                         R_DrawEntityBBoxes();
6702                         if (r_timereport_active)
6703                                 R_TimeReport("bboxes");
6704                 }
6705         }
6706
6707         R_MeshQueue_RenderTransparent();
6708         if (r_timereport_active)
6709                 R_TimeReport("drawtrans");
6710
6711         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))
6712         {
6713                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6714                 if (r_timereport_active)
6715                         R_TimeReport("worlddebug");
6716                 R_DrawModelsDebug();
6717                 if (r_timereport_active)
6718                         R_TimeReport("modeldebug");
6719         }
6720
6721         if (cl.csqc_vidvars.drawworld)
6722         {
6723                 R_Shadow_DrawCoronas();
6724                 if (r_timereport_active)
6725                         R_TimeReport("coronas");
6726         }
6727
6728 #if 0
6729         {
6730                 GL_DepthTest(false);
6731                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6732                 GL_Color(1, 1, 1, 1);
6733                 qglBegin(GL_POLYGON);
6734                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6735                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6736                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6737                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6738                 qglEnd();
6739                 qglBegin(GL_POLYGON);
6740                 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]);
6741                 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]);
6742                 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]);
6743                 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]);
6744                 qglEnd();
6745                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6746         }
6747 #endif
6748
6749         // don't let sound skip if going slow
6750         if (r_refdef.scene.extraupdate)
6751                 S_ExtraUpdate ();
6752
6753         R_ResetViewRendering2D();
6754 }
6755
6756 static const unsigned short bboxelements[36] =
6757 {
6758         5, 1, 3, 5, 3, 7,
6759         6, 2, 0, 6, 0, 4,
6760         7, 3, 2, 7, 2, 6,
6761         4, 0, 1, 4, 1, 5,
6762         4, 5, 7, 4, 7, 6,
6763         1, 0, 2, 1, 2, 3,
6764 };
6765
6766 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6767 {
6768         int i;
6769         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6770
6771         RSurf_ActiveWorldEntity();
6772
6773         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6774         GL_DepthMask(false);
6775         GL_DepthRange(0, 1);
6776         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6777 //      R_Mesh_ResetTextureState();
6778
6779         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6780         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6781         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6782         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6783         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6784         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6785         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6786         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6787         R_FillColors(color4f, 8, cr, cg, cb, ca);
6788         if (r_refdef.fogenabled)
6789         {
6790                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6791                 {
6792                         f1 = RSurf_FogVertex(v);
6793                         f2 = 1 - f1;
6794                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6795                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6796                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6797                 }
6798         }
6799         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6800         R_Mesh_ResetTextureState();
6801         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6802         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6803 }
6804
6805 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6806 {
6807         int i;
6808         float color[4];
6809         prvm_edict_t *edict;
6810         prvm_prog_t *prog_save = prog;
6811
6812         // this function draws bounding boxes of server entities
6813         if (!sv.active)
6814                 return;
6815
6816         GL_CullFace(GL_NONE);
6817         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6818
6819         prog = 0;
6820         SV_VM_Begin();
6821         for (i = 0;i < numsurfaces;i++)
6822         {
6823                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6824                 switch ((int)edict->fields.server->solid)
6825                 {
6826                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6827                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6828                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6829                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6830                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6831                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6832                 }
6833                 color[3] *= r_showbboxes.value;
6834                 color[3] = bound(0, color[3], 1);
6835                 GL_DepthTest(!r_showdisabledepthtest.integer);
6836                 GL_CullFace(r_refdef.view.cullface_front);
6837                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6838         }
6839         SV_VM_End();
6840         prog = prog_save;
6841 }
6842
6843 static void R_DrawEntityBBoxes(void)
6844 {
6845         int i;
6846         prvm_edict_t *edict;
6847         vec3_t center;
6848         prvm_prog_t *prog_save = prog;
6849
6850         // this function draws bounding boxes of server entities
6851         if (!sv.active)
6852                 return;
6853
6854         prog = 0;
6855         SV_VM_Begin();
6856         for (i = 0;i < prog->num_edicts;i++)
6857         {
6858                 edict = PRVM_EDICT_NUM(i);
6859                 if (edict->priv.server->free)
6860                         continue;
6861                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6862                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6863                         continue;
6864                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6865                         continue;
6866                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6867                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6868         }
6869         SV_VM_End();
6870         prog = prog_save;
6871 }
6872
6873 static const int nomodelelement3i[24] =
6874 {
6875         5, 2, 0,
6876         5, 1, 2,
6877         5, 0, 3,
6878         5, 3, 1,
6879         0, 2, 4,
6880         2, 1, 4,
6881         3, 0, 4,
6882         1, 3, 4
6883 };
6884
6885 static const unsigned short nomodelelement3s[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 float nomodelvertex3f[6*3] =
6898 {
6899         -16,   0,   0,
6900          16,   0,   0,
6901           0, -16,   0,
6902           0,  16,   0,
6903           0,   0, -16,
6904           0,   0,  16
6905 };
6906
6907 static const float nomodelcolor4f[6*4] =
6908 {
6909         0.0f, 0.0f, 0.5f, 1.0f,
6910         0.0f, 0.0f, 0.5f, 1.0f,
6911         0.0f, 0.5f, 0.0f, 1.0f,
6912         0.0f, 0.5f, 0.0f, 1.0f,
6913         0.5f, 0.0f, 0.0f, 1.0f,
6914         0.5f, 0.0f, 0.0f, 1.0f
6915 };
6916
6917 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6918 {
6919         int i;
6920         float f1, f2, *c;
6921         float color4f[6*4];
6922
6923         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);
6924
6925         // this is only called once per entity so numsurfaces is always 1, and
6926         // surfacelist is always {0}, so this code does not handle batches
6927
6928         if (rsurface.ent_flags & RENDER_ADDITIVE)
6929         {
6930                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6931                 GL_DepthMask(false);
6932         }
6933         else if (rsurface.colormod[3] < 1)
6934         {
6935                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6936                 GL_DepthMask(false);
6937         }
6938         else
6939         {
6940                 GL_BlendFunc(GL_ONE, GL_ZERO);
6941                 GL_DepthMask(true);
6942         }
6943         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6944         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6945         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6946         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6947         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6948         for (i = 0, c = color4f;i < 6;i++, c += 4)
6949         {
6950                 c[0] *= rsurface.colormod[0];
6951                 c[1] *= rsurface.colormod[1];
6952                 c[2] *= rsurface.colormod[2];
6953                 c[3] *= rsurface.colormod[3];
6954         }
6955         if (r_refdef.fogenabled)
6956         {
6957                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6958                 {
6959                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6960                         f2 = 1 - f1;
6961                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6962                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6963                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6964                 }
6965         }
6966 //      R_Mesh_ResetTextureState();
6967         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6968         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6969         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6970 }
6971
6972 void R_DrawNoModel(entity_render_t *ent)
6973 {
6974         vec3_t org;
6975         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6976         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6977                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6978         else
6979                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6980 }
6981
6982 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6983 {
6984         vec3_t right1, right2, diff, normal;
6985
6986         VectorSubtract (org2, org1, normal);
6987
6988         // calculate 'right' vector for start
6989         VectorSubtract (r_refdef.view.origin, org1, diff);
6990         CrossProduct (normal, diff, right1);
6991         VectorNormalize (right1);
6992
6993         // calculate 'right' vector for end
6994         VectorSubtract (r_refdef.view.origin, org2, diff);
6995         CrossProduct (normal, diff, right2);
6996         VectorNormalize (right2);
6997
6998         vert[ 0] = org1[0] + width * right1[0];
6999         vert[ 1] = org1[1] + width * right1[1];
7000         vert[ 2] = org1[2] + width * right1[2];
7001         vert[ 3] = org1[0] - width * right1[0];
7002         vert[ 4] = org1[1] - width * right1[1];
7003         vert[ 5] = org1[2] - width * right1[2];
7004         vert[ 6] = org2[0] - width * right2[0];
7005         vert[ 7] = org2[1] - width * right2[1];
7006         vert[ 8] = org2[2] - width * right2[2];
7007         vert[ 9] = org2[0] + width * right2[0];
7008         vert[10] = org2[1] + width * right2[1];
7009         vert[11] = org2[2] + width * right2[2];
7010 }
7011
7012 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)
7013 {
7014         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7015         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7016         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7017         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7018         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7019         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7020         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7021         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7022         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7023         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7024         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7025         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7026 }
7027
7028 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7029 {
7030         int i;
7031         float *vertex3f;
7032         float v[3];
7033         VectorSet(v, x, y, z);
7034         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7035                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7036                         break;
7037         if (i == mesh->numvertices)
7038         {
7039                 if (mesh->numvertices < mesh->maxvertices)
7040                 {
7041                         VectorCopy(v, vertex3f);
7042                         mesh->numvertices++;
7043                 }
7044                 return mesh->numvertices;
7045         }
7046         else
7047                 return i;
7048 }
7049
7050 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7051 {
7052         int i;
7053         int *e, element[3];
7054         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7055         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7056         e = mesh->element3i + mesh->numtriangles * 3;
7057         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7058         {
7059                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7060                 if (mesh->numtriangles < mesh->maxtriangles)
7061                 {
7062                         *e++ = element[0];
7063                         *e++ = element[1];
7064                         *e++ = element[2];
7065                         mesh->numtriangles++;
7066                 }
7067                 element[1] = element[2];
7068         }
7069 }
7070
7071 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7072 {
7073         int i;
7074         int *e, element[3];
7075         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7076         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7077         e = mesh->element3i + mesh->numtriangles * 3;
7078         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7079         {
7080                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7081                 if (mesh->numtriangles < mesh->maxtriangles)
7082                 {
7083                         *e++ = element[0];
7084                         *e++ = element[1];
7085                         *e++ = element[2];
7086                         mesh->numtriangles++;
7087                 }
7088                 element[1] = element[2];
7089         }
7090 }
7091
7092 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7093 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7094 {
7095         int planenum, planenum2;
7096         int w;
7097         int tempnumpoints;
7098         mplane_t *plane, *plane2;
7099         double maxdist;
7100         double temppoints[2][256*3];
7101         // figure out how large a bounding box we need to properly compute this brush
7102         maxdist = 0;
7103         for (w = 0;w < numplanes;w++)
7104                 maxdist = max(maxdist, fabs(planes[w].dist));
7105         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7106         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7107         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7108         {
7109                 w = 0;
7110                 tempnumpoints = 4;
7111                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7112                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7113                 {
7114                         if (planenum2 == planenum)
7115                                 continue;
7116                         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);
7117                         w = !w;
7118                 }
7119                 if (tempnumpoints < 3)
7120                         continue;
7121                 // generate elements forming a triangle fan for this polygon
7122                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7123         }
7124 }
7125
7126 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)
7127 {
7128         texturelayer_t *layer;
7129         layer = t->currentlayers + t->currentnumlayers++;
7130         layer->type = type;
7131         layer->depthmask = depthmask;
7132         layer->blendfunc1 = blendfunc1;
7133         layer->blendfunc2 = blendfunc2;
7134         layer->texture = texture;
7135         layer->texmatrix = *matrix;
7136         layer->color[0] = r;
7137         layer->color[1] = g;
7138         layer->color[2] = b;
7139         layer->color[3] = a;
7140 }
7141
7142 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7143 {
7144         if(parms[0] == 0 && parms[1] == 0)
7145                 return false;
7146         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7147                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7148                         return false;
7149         return true;
7150 }
7151
7152 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7153 {
7154         double index, f;
7155         index = parms[2] + r_refdef.scene.time * parms[3];
7156         index -= floor(index);
7157         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7158         {
7159         default:
7160         case Q3WAVEFUNC_NONE:
7161         case Q3WAVEFUNC_NOISE:
7162         case Q3WAVEFUNC_COUNT:
7163                 f = 0;
7164                 break;
7165         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7166         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7167         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7168         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7169         case Q3WAVEFUNC_TRIANGLE:
7170                 index *= 4;
7171                 f = index - floor(index);
7172                 if (index < 1)
7173                         f = f;
7174                 else if (index < 2)
7175                         f = 1 - f;
7176                 else if (index < 3)
7177                         f = -f;
7178                 else
7179                         f = -(1 - f);
7180                 break;
7181         }
7182         f = parms[0] + parms[1] * f;
7183         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7184                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7185         return (float) f;
7186 }
7187
7188 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7189 {
7190         int w, h, idx;
7191         float f;
7192         float tcmat[12];
7193         matrix4x4_t matrix, temp;
7194         switch(tcmod->tcmod)
7195         {
7196                 case Q3TCMOD_COUNT:
7197                 case Q3TCMOD_NONE:
7198                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7199                                 matrix = r_waterscrollmatrix;
7200                         else
7201                                 matrix = identitymatrix;
7202                         break;
7203                 case Q3TCMOD_ENTITYTRANSLATE:
7204                         // this is used in Q3 to allow the gamecode to control texcoord
7205                         // scrolling on the entity, which is not supported in darkplaces yet.
7206                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7207                         break;
7208                 case Q3TCMOD_ROTATE:
7209                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7210                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7211                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7212                         break;
7213                 case Q3TCMOD_SCALE:
7214                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7215                         break;
7216                 case Q3TCMOD_SCROLL:
7217                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7218                         break;
7219                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7220                         w = (int) tcmod->parms[0];
7221                         h = (int) tcmod->parms[1];
7222                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7223                         f = f - floor(f);
7224                         idx = (int) floor(f * w * h);
7225                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7226                         break;
7227                 case Q3TCMOD_STRETCH:
7228                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7229                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7230                         break;
7231                 case Q3TCMOD_TRANSFORM:
7232                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7233                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7234                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7235                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7236                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7237                         break;
7238                 case Q3TCMOD_TURBULENT:
7239                         // this is handled in the RSurf_PrepareVertices function
7240                         matrix = identitymatrix;
7241                         break;
7242         }
7243         temp = *texmatrix;
7244         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7245 }
7246
7247 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7248 {
7249         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7250         char name[MAX_QPATH];
7251         skinframe_t *skinframe;
7252         unsigned char pixels[296*194];
7253         strlcpy(cache->name, skinname, sizeof(cache->name));
7254         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7255         if (developer_loading.integer)
7256                 Con_Printf("loading %s\n", name);
7257         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7258         if (!skinframe || !skinframe->base)
7259         {
7260                 unsigned char *f;
7261                 fs_offset_t filesize;
7262                 skinframe = NULL;
7263                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7264                 if (f)
7265                 {
7266                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7267                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7268                         Mem_Free(f);
7269                 }
7270         }
7271         cache->skinframe = skinframe;
7272 }
7273
7274 texture_t *R_GetCurrentTexture(texture_t *t)
7275 {
7276         int i;
7277         const entity_render_t *ent = rsurface.entity;
7278         dp_model_t *model = ent->model;
7279         q3shaderinfo_layer_tcmod_t *tcmod;
7280
7281         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7282                 return t->currentframe;
7283         t->update_lastrenderframe = r_textureframe;
7284         t->update_lastrenderentity = (void *)ent;
7285
7286         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7287                 t->camera_entity = ent->entitynumber;
7288         else
7289                 t->camera_entity = 0;
7290
7291         // switch to an alternate material if this is a q1bsp animated material
7292         {
7293                 texture_t *texture = t;
7294                 int s = rsurface.ent_skinnum;
7295                 if ((unsigned int)s >= (unsigned int)model->numskins)
7296                         s = 0;
7297                 if (model->skinscenes)
7298                 {
7299                         if (model->skinscenes[s].framecount > 1)
7300                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7301                         else
7302                                 s = model->skinscenes[s].firstframe;
7303                 }
7304                 if (s > 0)
7305                         t = t + s * model->num_surfaces;
7306                 if (t->animated)
7307                 {
7308                         // use an alternate animation if the entity's frame is not 0,
7309                         // and only if the texture has an alternate animation
7310                         if (rsurface.ent_alttextures && t->anim_total[1])
7311                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7312                         else
7313                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7314                 }
7315                 texture->currentframe = t;
7316         }
7317
7318         // update currentskinframe to be a qw skin or animation frame
7319         if (rsurface.ent_qwskin >= 0)
7320         {
7321                 i = rsurface.ent_qwskin;
7322                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7323                 {
7324                         r_qwskincache_size = cl.maxclients;
7325                         if (r_qwskincache)
7326                                 Mem_Free(r_qwskincache);
7327                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7328                 }
7329                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7330                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7331                 t->currentskinframe = r_qwskincache[i].skinframe;
7332                 if (t->currentskinframe == NULL)
7333                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7334         }
7335         else if (t->numskinframes >= 2)
7336                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7337         if (t->backgroundnumskinframes >= 2)
7338                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7339
7340         t->currentmaterialflags = t->basematerialflags;
7341         t->currentalpha = rsurface.colormod[3];
7342         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7343                 t->currentalpha *= r_wateralpha.value;
7344         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7345                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7346         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7347                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7348         if (!(rsurface.ent_flags & RENDER_LIGHT))
7349                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7350         else if (FAKELIGHT_ENABLED)
7351         {
7352                         // no modellight if using fakelight for the map
7353         }
7354         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7355         {
7356                 // pick a model lighting mode
7357                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7358                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7359                 else
7360                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7361         }
7362         if (rsurface.ent_flags & RENDER_ADDITIVE)
7363                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7364         else if (t->currentalpha < 1)
7365                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7366         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7367                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7368         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7369                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7370         if (t->backgroundnumskinframes)
7371                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7372         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7373         {
7374                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7375                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7376         }
7377         else
7378                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7379         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7380                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7381
7382         // there is no tcmod
7383         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7384         {
7385                 t->currenttexmatrix = r_waterscrollmatrix;
7386                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7387         }
7388         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7389         {
7390                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7391                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7392         }
7393
7394         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7395                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7396         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7397                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7398
7399         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7400         if (t->currentskinframe->qpixels)
7401                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7402         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7403         if (!t->basetexture)
7404                 t->basetexture = r_texture_notexture;
7405         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7406         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7407         t->nmaptexture = t->currentskinframe->nmap;
7408         if (!t->nmaptexture)
7409                 t->nmaptexture = r_texture_blanknormalmap;
7410         t->glosstexture = r_texture_black;
7411         t->glowtexture = t->currentskinframe->glow;
7412         t->fogtexture = t->currentskinframe->fog;
7413         t->reflectmasktexture = t->currentskinframe->reflect;
7414         if (t->backgroundnumskinframes)
7415         {
7416                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7417                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7418                 t->backgroundglosstexture = r_texture_black;
7419                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7420                 if (!t->backgroundnmaptexture)
7421                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7422         }
7423         else
7424         {
7425                 t->backgroundbasetexture = r_texture_white;
7426                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7427                 t->backgroundglosstexture = r_texture_black;
7428                 t->backgroundglowtexture = NULL;
7429         }
7430         t->specularpower = r_shadow_glossexponent.value;
7431         // TODO: store reference values for these in the texture?
7432         t->specularscale = 0;
7433         if (r_shadow_gloss.integer > 0)
7434         {
7435                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7436                 {
7437                         if (r_shadow_glossintensity.value > 0)
7438                         {
7439                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7440                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7441                                 t->specularscale = r_shadow_glossintensity.value;
7442                         }
7443                 }
7444                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7445                 {
7446                         t->glosstexture = r_texture_white;
7447                         t->backgroundglosstexture = r_texture_white;
7448                         t->specularscale = r_shadow_gloss2intensity.value;
7449                         t->specularpower = r_shadow_gloss2exponent.value;
7450                 }
7451         }
7452         t->specularscale *= t->specularscalemod;
7453         t->specularpower *= t->specularpowermod;
7454
7455         // lightmaps mode looks bad with dlights using actual texturing, so turn
7456         // off the colormap and glossmap, but leave the normalmap on as it still
7457         // accurately represents the shading involved
7458         if (gl_lightmaps.integer)
7459         {
7460                 t->basetexture = r_texture_grey128;
7461                 t->pantstexture = r_texture_black;
7462                 t->shirttexture = r_texture_black;
7463                 t->nmaptexture = r_texture_blanknormalmap;
7464                 t->glosstexture = r_texture_black;
7465                 t->glowtexture = NULL;
7466                 t->fogtexture = NULL;
7467                 t->reflectmasktexture = NULL;
7468                 t->backgroundbasetexture = NULL;
7469                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7470                 t->backgroundglosstexture = r_texture_black;
7471                 t->backgroundglowtexture = NULL;
7472                 t->specularscale = 0;
7473                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7474         }
7475
7476         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7477         VectorClear(t->dlightcolor);
7478         t->currentnumlayers = 0;
7479         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7480         {
7481                 int blendfunc1, blendfunc2;
7482                 qboolean depthmask;
7483                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7484                 {
7485                         blendfunc1 = GL_SRC_ALPHA;
7486                         blendfunc2 = GL_ONE;
7487                 }
7488                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7489                 {
7490                         blendfunc1 = GL_SRC_ALPHA;
7491                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7492                 }
7493                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7494                 {
7495                         blendfunc1 = t->customblendfunc[0];
7496                         blendfunc2 = t->customblendfunc[1];
7497                 }
7498                 else
7499                 {
7500                         blendfunc1 = GL_ONE;
7501                         blendfunc2 = GL_ZERO;
7502                 }
7503                 // don't colormod evilblend textures
7504                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7505                         VectorSet(t->lightmapcolor, 1, 1, 1);
7506                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7507                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7508                 {
7509                         // fullbright is not affected by r_refdef.lightmapintensity
7510                         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]);
7511                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7512                                 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]);
7513                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7514                                 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]);
7515                 }
7516                 else
7517                 {
7518                         vec3_t ambientcolor;
7519                         float colorscale;
7520                         // set the color tint used for lights affecting this surface
7521                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7522                         colorscale = 2;
7523                         // q3bsp has no lightmap updates, so the lightstylevalue that
7524                         // would normally be baked into the lightmap must be
7525                         // applied to the color
7526                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7527                         if (model->type == mod_brushq3)
7528                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7529                         colorscale *= r_refdef.lightmapintensity;
7530                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7531                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7532                         // basic lit geometry
7533                         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]);
7534                         // add pants/shirt if needed
7535                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7536                                 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]);
7537                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7538                                 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]);
7539                         // now add ambient passes if needed
7540                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7541                         {
7542                                 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]);
7543                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7544                                         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]);
7545                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7546                                         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]);
7547                         }
7548                 }
7549                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7550                         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]);
7551                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7552                 {
7553                         // if this is opaque use alpha blend which will darken the earlier
7554                         // passes cheaply.
7555                         //
7556                         // if this is an alpha blended material, all the earlier passes
7557                         // were darkened by fog already, so we only need to add the fog
7558                         // color ontop through the fog mask texture
7559                         //
7560                         // if this is an additive blended material, all the earlier passes
7561                         // were darkened by fog already, and we should not add fog color
7562                         // (because the background was not darkened, there is no fog color
7563                         // that was lost behind it).
7564                         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]);
7565                 }
7566         }
7567
7568         return t->currentframe;
7569 }
7570
7571 rsurfacestate_t rsurface;
7572
7573 void RSurf_ActiveWorldEntity(void)
7574 {
7575         dp_model_t *model = r_refdef.scene.worldmodel;
7576         //if (rsurface.entity == r_refdef.scene.worldentity)
7577         //      return;
7578         rsurface.entity = r_refdef.scene.worldentity;
7579         rsurface.skeleton = NULL;
7580         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7581         rsurface.ent_skinnum = 0;
7582         rsurface.ent_qwskin = -1;
7583         rsurface.ent_shadertime = 0;
7584         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7585         rsurface.matrix = identitymatrix;
7586         rsurface.inversematrix = identitymatrix;
7587         rsurface.matrixscale = 1;
7588         rsurface.inversematrixscale = 1;
7589         R_EntityMatrix(&identitymatrix);
7590         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7591         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7592         rsurface.fograngerecip = r_refdef.fograngerecip;
7593         rsurface.fogheightfade = r_refdef.fogheightfade;
7594         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7595         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7596         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7597         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7598         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7599         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7600         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7601         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7602         rsurface.colormod[3] = 1;
7603         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);
7604         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7605         rsurface.frameblend[0].lerp = 1;
7606         rsurface.ent_alttextures = false;
7607         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7608         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7609         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7610         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7611         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7612         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7613         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7614         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7615         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7616         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7617         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7618         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7619         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7620         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7621         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7622         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7623         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7624         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7625         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7626         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7627         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7628         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7629         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7630         rsurface.modelelement3i = model->surfmesh.data_element3i;
7631         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7632         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7633         rsurface.modelelement3s = model->surfmesh.data_element3s;
7634         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7635         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7636         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7637         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7638         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7639         rsurface.modelsurfaces = model->data_surfaces;
7640         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7641         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7642         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7643         rsurface.modelgeneratedvertex = false;
7644         rsurface.batchgeneratedvertex = false;
7645         rsurface.batchfirstvertex = 0;
7646         rsurface.batchnumvertices = 0;
7647         rsurface.batchfirsttriangle = 0;
7648         rsurface.batchnumtriangles = 0;
7649         rsurface.batchvertex3f  = NULL;
7650         rsurface.batchvertex3f_vertexbuffer = NULL;
7651         rsurface.batchvertex3f_bufferoffset = 0;
7652         rsurface.batchsvector3f = NULL;
7653         rsurface.batchsvector3f_vertexbuffer = NULL;
7654         rsurface.batchsvector3f_bufferoffset = 0;
7655         rsurface.batchtvector3f = NULL;
7656         rsurface.batchtvector3f_vertexbuffer = NULL;
7657         rsurface.batchtvector3f_bufferoffset = 0;
7658         rsurface.batchnormal3f  = NULL;
7659         rsurface.batchnormal3f_vertexbuffer = NULL;
7660         rsurface.batchnormal3f_bufferoffset = 0;
7661         rsurface.batchlightmapcolor4f = NULL;
7662         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7663         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7664         rsurface.batchtexcoordtexture2f = NULL;
7665         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7666         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7667         rsurface.batchtexcoordlightmap2f = NULL;
7668         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7669         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7670         rsurface.batchvertexmesh = NULL;
7671         rsurface.batchvertexmeshbuffer = NULL;
7672         rsurface.batchvertex3fbuffer = NULL;
7673         rsurface.batchelement3i = NULL;
7674         rsurface.batchelement3i_indexbuffer = NULL;
7675         rsurface.batchelement3i_bufferoffset = 0;
7676         rsurface.batchelement3s = NULL;
7677         rsurface.batchelement3s_indexbuffer = NULL;
7678         rsurface.batchelement3s_bufferoffset = 0;
7679         rsurface.passcolor4f = NULL;
7680         rsurface.passcolor4f_vertexbuffer = NULL;
7681         rsurface.passcolor4f_bufferoffset = 0;
7682 }
7683
7684 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7685 {
7686         dp_model_t *model = ent->model;
7687         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7688         //      return;
7689         rsurface.entity = (entity_render_t *)ent;
7690         rsurface.skeleton = ent->skeleton;
7691         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7692         rsurface.ent_skinnum = ent->skinnum;
7693         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;
7694         rsurface.ent_shadertime = ent->shadertime;
7695         rsurface.ent_flags = ent->flags;
7696         rsurface.matrix = ent->matrix;
7697         rsurface.inversematrix = ent->inversematrix;
7698         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7699         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7700         R_EntityMatrix(&rsurface.matrix);
7701         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7702         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7703         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7704         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7705         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7706         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7707         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7708         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7709         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7710         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7711         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7712         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7713         rsurface.colormod[3] = ent->alpha;
7714         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7715         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7716         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7717         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7718         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7719         if (ent->model->brush.submodel && !prepass)
7720         {
7721                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7722                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7723         }
7724         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7725         {
7726                 if (ent->animcache_vertex3f)
7727                 {
7728                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7729                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7730                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7731                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7732                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7733                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7734                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7735                 }
7736                 else if (wanttangents)
7737                 {
7738                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7739                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7740                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7741                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7742                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7743                         rsurface.modelvertexmesh = NULL;
7744                         rsurface.modelvertexmeshbuffer = NULL;
7745                         rsurface.modelvertex3fbuffer = NULL;
7746                 }
7747                 else if (wantnormals)
7748                 {
7749                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7750                         rsurface.modelsvector3f = NULL;
7751                         rsurface.modeltvector3f = NULL;
7752                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7753                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7754                         rsurface.modelvertexmesh = NULL;
7755                         rsurface.modelvertexmeshbuffer = NULL;
7756                         rsurface.modelvertex3fbuffer = NULL;
7757                 }
7758                 else
7759                 {
7760                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7761                         rsurface.modelsvector3f = NULL;
7762                         rsurface.modeltvector3f = NULL;
7763                         rsurface.modelnormal3f = NULL;
7764                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7765                         rsurface.modelvertexmesh = NULL;
7766                         rsurface.modelvertexmeshbuffer = NULL;
7767                         rsurface.modelvertex3fbuffer = NULL;
7768                 }
7769                 rsurface.modelvertex3f_vertexbuffer = 0;
7770                 rsurface.modelvertex3f_bufferoffset = 0;
7771                 rsurface.modelsvector3f_vertexbuffer = 0;
7772                 rsurface.modelsvector3f_bufferoffset = 0;
7773                 rsurface.modeltvector3f_vertexbuffer = 0;
7774                 rsurface.modeltvector3f_bufferoffset = 0;
7775                 rsurface.modelnormal3f_vertexbuffer = 0;
7776                 rsurface.modelnormal3f_bufferoffset = 0;
7777                 rsurface.modelgeneratedvertex = true;
7778         }
7779         else
7780         {
7781                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7782                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7783                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7784                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7785                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7786                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7787                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7788                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7789                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7790                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7791                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7792                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7793                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7794                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7795                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7796                 rsurface.modelgeneratedvertex = false;
7797         }
7798         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7799         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7800         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7801         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7802         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7803         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7804         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7805         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7806         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7807         rsurface.modelelement3i = model->surfmesh.data_element3i;
7808         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7809         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7810         rsurface.modelelement3s = model->surfmesh.data_element3s;
7811         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7812         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7813         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7814         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7815         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7816         rsurface.modelsurfaces = model->data_surfaces;
7817         rsurface.batchgeneratedvertex = false;
7818         rsurface.batchfirstvertex = 0;
7819         rsurface.batchnumvertices = 0;
7820         rsurface.batchfirsttriangle = 0;
7821         rsurface.batchnumtriangles = 0;
7822         rsurface.batchvertex3f  = NULL;
7823         rsurface.batchvertex3f_vertexbuffer = NULL;
7824         rsurface.batchvertex3f_bufferoffset = 0;
7825         rsurface.batchsvector3f = NULL;
7826         rsurface.batchsvector3f_vertexbuffer = NULL;
7827         rsurface.batchsvector3f_bufferoffset = 0;
7828         rsurface.batchtvector3f = NULL;
7829         rsurface.batchtvector3f_vertexbuffer = NULL;
7830         rsurface.batchtvector3f_bufferoffset = 0;
7831         rsurface.batchnormal3f  = NULL;
7832         rsurface.batchnormal3f_vertexbuffer = NULL;
7833         rsurface.batchnormal3f_bufferoffset = 0;
7834         rsurface.batchlightmapcolor4f = NULL;
7835         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7836         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7837         rsurface.batchtexcoordtexture2f = NULL;
7838         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7839         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7840         rsurface.batchtexcoordlightmap2f = NULL;
7841         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7842         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7843         rsurface.batchvertexmesh = NULL;
7844         rsurface.batchvertexmeshbuffer = NULL;
7845         rsurface.batchvertex3fbuffer = NULL;
7846         rsurface.batchelement3i = NULL;
7847         rsurface.batchelement3i_indexbuffer = NULL;
7848         rsurface.batchelement3i_bufferoffset = 0;
7849         rsurface.batchelement3s = NULL;
7850         rsurface.batchelement3s_indexbuffer = NULL;
7851         rsurface.batchelement3s_bufferoffset = 0;
7852         rsurface.passcolor4f = NULL;
7853         rsurface.passcolor4f_vertexbuffer = NULL;
7854         rsurface.passcolor4f_bufferoffset = 0;
7855 }
7856
7857 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)
7858 {
7859         rsurface.entity = r_refdef.scene.worldentity;
7860         rsurface.skeleton = NULL;
7861         rsurface.ent_skinnum = 0;
7862         rsurface.ent_qwskin = -1;
7863         rsurface.ent_shadertime = shadertime;
7864         rsurface.ent_flags = entflags;
7865         rsurface.modelnumvertices = numvertices;
7866         rsurface.modelnumtriangles = numtriangles;
7867         rsurface.matrix = *matrix;
7868         rsurface.inversematrix = *inversematrix;
7869         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7870         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7871         R_EntityMatrix(&rsurface.matrix);
7872         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7873         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7874         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7875         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7876         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7877         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7878         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7879         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7880         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7881         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7882         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7883         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7884         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);
7885         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7886         rsurface.frameblend[0].lerp = 1;
7887         rsurface.ent_alttextures = false;
7888         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7889         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7890         if (wanttangents)
7891         {
7892                 rsurface.modelvertex3f = (float *)vertex3f;
7893                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7894                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7895                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7896         }
7897         else if (wantnormals)
7898         {
7899                 rsurface.modelvertex3f = (float *)vertex3f;
7900                 rsurface.modelsvector3f = NULL;
7901                 rsurface.modeltvector3f = NULL;
7902                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7903         }
7904         else
7905         {
7906                 rsurface.modelvertex3f = (float *)vertex3f;
7907                 rsurface.modelsvector3f = NULL;
7908                 rsurface.modeltvector3f = NULL;
7909                 rsurface.modelnormal3f = NULL;
7910         }
7911         rsurface.modelvertexmesh = NULL;
7912         rsurface.modelvertexmeshbuffer = NULL;
7913         rsurface.modelvertex3fbuffer = NULL;
7914         rsurface.modelvertex3f_vertexbuffer = 0;
7915         rsurface.modelvertex3f_bufferoffset = 0;
7916         rsurface.modelsvector3f_vertexbuffer = 0;
7917         rsurface.modelsvector3f_bufferoffset = 0;
7918         rsurface.modeltvector3f_vertexbuffer = 0;
7919         rsurface.modeltvector3f_bufferoffset = 0;
7920         rsurface.modelnormal3f_vertexbuffer = 0;
7921         rsurface.modelnormal3f_bufferoffset = 0;
7922         rsurface.modelgeneratedvertex = true;
7923         rsurface.modellightmapcolor4f  = (float *)color4f;
7924         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7925         rsurface.modellightmapcolor4f_bufferoffset = 0;
7926         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7927         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7928         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7929         rsurface.modeltexcoordlightmap2f  = NULL;
7930         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7931         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7932         rsurface.modelelement3i = (int *)element3i;
7933         rsurface.modelelement3i_indexbuffer = NULL;
7934         rsurface.modelelement3i_bufferoffset = 0;
7935         rsurface.modelelement3s = (unsigned short *)element3s;
7936         rsurface.modelelement3s_indexbuffer = NULL;
7937         rsurface.modelelement3s_bufferoffset = 0;
7938         rsurface.modellightmapoffsets = NULL;
7939         rsurface.modelsurfaces = NULL;
7940         rsurface.batchgeneratedvertex = false;
7941         rsurface.batchfirstvertex = 0;
7942         rsurface.batchnumvertices = 0;
7943         rsurface.batchfirsttriangle = 0;
7944         rsurface.batchnumtriangles = 0;
7945         rsurface.batchvertex3f  = NULL;
7946         rsurface.batchvertex3f_vertexbuffer = NULL;
7947         rsurface.batchvertex3f_bufferoffset = 0;
7948         rsurface.batchsvector3f = NULL;
7949         rsurface.batchsvector3f_vertexbuffer = NULL;
7950         rsurface.batchsvector3f_bufferoffset = 0;
7951         rsurface.batchtvector3f = NULL;
7952         rsurface.batchtvector3f_vertexbuffer = NULL;
7953         rsurface.batchtvector3f_bufferoffset = 0;
7954         rsurface.batchnormal3f  = NULL;
7955         rsurface.batchnormal3f_vertexbuffer = NULL;
7956         rsurface.batchnormal3f_bufferoffset = 0;
7957         rsurface.batchlightmapcolor4f = NULL;
7958         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7959         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7960         rsurface.batchtexcoordtexture2f = NULL;
7961         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7962         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7963         rsurface.batchtexcoordlightmap2f = NULL;
7964         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7965         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7966         rsurface.batchvertexmesh = NULL;
7967         rsurface.batchvertexmeshbuffer = NULL;
7968         rsurface.batchvertex3fbuffer = NULL;
7969         rsurface.batchelement3i = NULL;
7970         rsurface.batchelement3i_indexbuffer = NULL;
7971         rsurface.batchelement3i_bufferoffset = 0;
7972         rsurface.batchelement3s = NULL;
7973         rsurface.batchelement3s_indexbuffer = NULL;
7974         rsurface.batchelement3s_bufferoffset = 0;
7975         rsurface.passcolor4f = NULL;
7976         rsurface.passcolor4f_vertexbuffer = NULL;
7977         rsurface.passcolor4f_bufferoffset = 0;
7978
7979         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7980         {
7981                 if ((wantnormals || wanttangents) && !normal3f)
7982                 {
7983                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7984                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7985                 }
7986                 if (wanttangents && !svector3f)
7987                 {
7988                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7989                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7990                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7991                 }
7992         }
7993 }
7994
7995 float RSurf_FogPoint(const float *v)
7996 {
7997         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7998         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7999         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8000         float FogHeightFade = r_refdef.fogheightfade;
8001         float fogfrac;
8002         unsigned int fogmasktableindex;
8003         if (r_refdef.fogplaneviewabove)
8004                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8005         else
8006                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8007         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8008         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8009 }
8010
8011 float RSurf_FogVertex(const float *v)
8012 {
8013         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8014         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8015         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8016         float FogHeightFade = rsurface.fogheightfade;
8017         float fogfrac;
8018         unsigned int fogmasktableindex;
8019         if (r_refdef.fogplaneviewabove)
8020                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8021         else
8022                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8023         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8024         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8025 }
8026
8027 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8028 {
8029         int i;
8030         for (i = 0;i < numelements;i++)
8031                 outelement3i[i] = inelement3i[i] + adjust;
8032 }
8033
8034 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8035 extern cvar_t gl_vbo;
8036 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8037 {
8038         int deformindex;
8039         int firsttriangle;
8040         int numtriangles;
8041         int firstvertex;
8042         int endvertex;
8043         int numvertices;
8044         int surfacefirsttriangle;
8045         int surfacenumtriangles;
8046         int surfacefirstvertex;
8047         int surfaceendvertex;
8048         int surfacenumvertices;
8049         int batchnumvertices;
8050         int batchnumtriangles;
8051         int needsupdate;
8052         int i, j;
8053         qboolean gaps;
8054         qboolean dynamicvertex;
8055         float amplitude;
8056         float animpos;
8057         float scale;
8058         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8059         float waveparms[4];
8060         q3shaderinfo_deform_t *deform;
8061         const msurface_t *surface, *firstsurface;
8062         r_vertexmesh_t *vertexmesh;
8063         if (!texturenumsurfaces)
8064                 return;
8065         // find vertex range of this surface batch
8066         gaps = false;
8067         firstsurface = texturesurfacelist[0];
8068         firsttriangle = firstsurface->num_firsttriangle;
8069         batchnumvertices = 0;
8070         batchnumtriangles = 0;
8071         firstvertex = endvertex = firstsurface->num_firstvertex;
8072         for (i = 0;i < texturenumsurfaces;i++)
8073         {
8074                 surface = texturesurfacelist[i];
8075                 if (surface != firstsurface + i)
8076                         gaps = true;
8077                 surfacefirstvertex = surface->num_firstvertex;
8078                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8079                 surfacenumvertices = surface->num_vertices;
8080                 surfacenumtriangles = surface->num_triangles;
8081                 if (firstvertex > surfacefirstvertex)
8082                         firstvertex = surfacefirstvertex;
8083                 if (endvertex < surfaceendvertex)
8084                         endvertex = surfaceendvertex;
8085                 batchnumvertices += surfacenumvertices;
8086                 batchnumtriangles += surfacenumtriangles;
8087         }
8088
8089         // we now know the vertex range used, and if there are any gaps in it
8090         rsurface.batchfirstvertex = firstvertex;
8091         rsurface.batchnumvertices = endvertex - firstvertex;
8092         rsurface.batchfirsttriangle = firsttriangle;
8093         rsurface.batchnumtriangles = batchnumtriangles;
8094
8095         // this variable holds flags for which properties have been updated that
8096         // may require regenerating vertexmesh array...
8097         needsupdate = 0;
8098
8099         // check if any dynamic vertex processing must occur
8100         dynamicvertex = false;
8101
8102         // if there is a chance of animated vertex colors, it's a dynamic batch
8103         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8104         {
8105                 dynamicvertex = true;
8106                 batchneed |= BATCHNEED_NOGAPS;
8107                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8108         }
8109
8110         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8111         {
8112                 switch (deform->deform)
8113                 {
8114                 default:
8115                 case Q3DEFORM_PROJECTIONSHADOW:
8116                 case Q3DEFORM_TEXT0:
8117                 case Q3DEFORM_TEXT1:
8118                 case Q3DEFORM_TEXT2:
8119                 case Q3DEFORM_TEXT3:
8120                 case Q3DEFORM_TEXT4:
8121                 case Q3DEFORM_TEXT5:
8122                 case Q3DEFORM_TEXT6:
8123                 case Q3DEFORM_TEXT7:
8124                 case Q3DEFORM_NONE:
8125                         break;
8126                 case Q3DEFORM_AUTOSPRITE:
8127                         dynamicvertex = true;
8128                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8129                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8130                         break;
8131                 case Q3DEFORM_AUTOSPRITE2:
8132                         dynamicvertex = true;
8133                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8134                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8135                         break;
8136                 case Q3DEFORM_NORMAL:
8137                         dynamicvertex = true;
8138                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8139                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8140                         break;
8141                 case Q3DEFORM_WAVE:
8142                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8143                                 break; // if wavefunc is a nop, ignore this transform
8144                         dynamicvertex = true;
8145                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8146                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8147                         break;
8148                 case Q3DEFORM_BULGE:
8149                         dynamicvertex = true;
8150                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8151                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8152                         break;
8153                 case Q3DEFORM_MOVE:
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_NOGAPS;
8158                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8159                         break;
8160                 }
8161         }
8162         switch(rsurface.texture->tcgen.tcgen)
8163         {
8164         default:
8165         case Q3TCGEN_TEXTURE:
8166                 break;
8167         case Q3TCGEN_LIGHTMAP:
8168                 dynamicvertex = true;
8169                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8170                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8171                 break;
8172         case Q3TCGEN_VECTOR:
8173                 dynamicvertex = true;
8174                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8175                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8176                 break;
8177         case Q3TCGEN_ENVIRONMENT:
8178                 dynamicvertex = true;
8179                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8180                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8181                 break;
8182         }
8183         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8184         {
8185                 dynamicvertex = true;
8186                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8187                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8188         }
8189
8190         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8191         {
8192                 dynamicvertex = true;
8193                 batchneed |= BATCHNEED_NOGAPS;
8194                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8195         }
8196
8197         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8198         {
8199                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8200                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8201                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8202                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8203                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8204                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8205                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8206         }
8207
8208         // when the model data has no vertex buffer (dynamic mesh), we need to
8209         // eliminate gaps
8210         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8211                 batchneed |= BATCHNEED_NOGAPS;
8212
8213         // if needsupdate, we have to do a dynamic vertex batch for sure
8214         if (needsupdate & batchneed)
8215                 dynamicvertex = true;
8216
8217         // see if we need to build vertexmesh from arrays
8218         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8219                 dynamicvertex = true;
8220
8221         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8222         // also some drivers strongly dislike firstvertex
8223         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8224                 dynamicvertex = true;
8225
8226         rsurface.batchvertex3f = rsurface.modelvertex3f;
8227         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8228         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8229         rsurface.batchsvector3f = rsurface.modelsvector3f;
8230         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8231         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8232         rsurface.batchtvector3f = rsurface.modeltvector3f;
8233         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8234         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8235         rsurface.batchnormal3f = rsurface.modelnormal3f;
8236         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8237         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8238         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8239         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8240         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8241         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8242         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8243         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8244         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8245         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8246         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8247         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8248         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8249         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8250         rsurface.batchelement3i = rsurface.modelelement3i;
8251         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8252         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8253         rsurface.batchelement3s = rsurface.modelelement3s;
8254         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8255         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8256
8257         // if any dynamic vertex processing has to occur in software, we copy the
8258         // entire surface list together before processing to rebase the vertices
8259         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8260         //
8261         // if any gaps exist and we do not have a static vertex buffer, we have to
8262         // copy the surface list together to avoid wasting upload bandwidth on the
8263         // vertices in the gaps.
8264         //
8265         // if gaps exist and we have a static vertex buffer, we still have to
8266         // combine the index buffer ranges into one dynamic index buffer.
8267         //
8268         // in all cases we end up with data that can be drawn in one call.
8269
8270         if (!dynamicvertex)
8271         {
8272                 // static vertex data, just set pointers...
8273                 rsurface.batchgeneratedvertex = false;
8274                 // if there are gaps, we want to build a combined index buffer,
8275                 // otherwise use the original static buffer with an appropriate offset
8276                 if (gaps)
8277                 {
8278                         // build a new triangle elements array for this batch
8279                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8280                         rsurface.batchfirsttriangle = 0;
8281                         numtriangles = 0;
8282                         for (i = 0;i < texturenumsurfaces;i++)
8283                         {
8284                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8285                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8286                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8287                                 numtriangles += surfacenumtriangles;
8288                         }
8289                         rsurface.batchelement3i_indexbuffer = NULL;
8290                         rsurface.batchelement3i_bufferoffset = 0;
8291                         rsurface.batchelement3s = NULL;
8292                         rsurface.batchelement3s_indexbuffer = NULL;
8293                         rsurface.batchelement3s_bufferoffset = 0;
8294                         if (endvertex <= 65536)
8295                         {
8296                                 // make a 16bit (unsigned short) index array if possible
8297                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8298                                 for (i = 0;i < numtriangles*3;i++)
8299                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8300                         }
8301                 }
8302                 return;
8303         }
8304
8305         // something needs software processing, do it for real...
8306         // we only directly handle separate array data in this case and then
8307         // generate interleaved data if needed...
8308         rsurface.batchgeneratedvertex = true;
8309
8310         // now copy the vertex data into a combined array and make an index array
8311         // (this is what Quake3 does all the time)
8312         //if (gaps || rsurface.batchfirstvertex)
8313         {
8314                 rsurface.batchvertex3fbuffer = NULL;
8315                 rsurface.batchvertexmesh = NULL;
8316                 rsurface.batchvertexmeshbuffer = NULL;
8317                 rsurface.batchvertex3f = NULL;
8318                 rsurface.batchvertex3f_vertexbuffer = NULL;
8319                 rsurface.batchvertex3f_bufferoffset = 0;
8320                 rsurface.batchsvector3f = NULL;
8321                 rsurface.batchsvector3f_vertexbuffer = NULL;
8322                 rsurface.batchsvector3f_bufferoffset = 0;
8323                 rsurface.batchtvector3f = NULL;
8324                 rsurface.batchtvector3f_vertexbuffer = NULL;
8325                 rsurface.batchtvector3f_bufferoffset = 0;
8326                 rsurface.batchnormal3f = NULL;
8327                 rsurface.batchnormal3f_vertexbuffer = NULL;
8328                 rsurface.batchnormal3f_bufferoffset = 0;
8329                 rsurface.batchlightmapcolor4f = NULL;
8330                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8331                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8332                 rsurface.batchtexcoordtexture2f = NULL;
8333                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8334                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8335                 rsurface.batchtexcoordlightmap2f = NULL;
8336                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8337                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8338                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8339                 rsurface.batchelement3i_indexbuffer = NULL;
8340                 rsurface.batchelement3i_bufferoffset = 0;
8341                 rsurface.batchelement3s = NULL;
8342                 rsurface.batchelement3s_indexbuffer = NULL;
8343                 rsurface.batchelement3s_bufferoffset = 0;
8344                 // we'll only be setting up certain arrays as needed
8345                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8346                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8347                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8348                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8349                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8350                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8351                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8352                 {
8353                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8354                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8355                 }
8356                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8357                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8358                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8359                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8360                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8361                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8362                 numvertices = 0;
8363                 numtriangles = 0;
8364                 for (i = 0;i < texturenumsurfaces;i++)
8365                 {
8366                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8367                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8368                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8369                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8370                         // copy only the data requested
8371                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8372                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8373                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8374                         {
8375                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8376                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8377                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8378                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8379                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8380                                 {
8381                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8382                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8383                                 }
8384                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8385                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8386                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8387                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8388                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8389                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8390                         }
8391                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8392                         numvertices += surfacenumvertices;
8393                         numtriangles += surfacenumtriangles;
8394                 }
8395
8396                 // generate a 16bit index array as well if possible
8397                 // (in general, dynamic batches fit)
8398                 if (numvertices <= 65536)
8399                 {
8400                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8401                         for (i = 0;i < numtriangles*3;i++)
8402                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8403                 }
8404
8405                 // since we've copied everything, the batch now starts at 0
8406                 rsurface.batchfirstvertex = 0;
8407                 rsurface.batchnumvertices = batchnumvertices;
8408                 rsurface.batchfirsttriangle = 0;
8409                 rsurface.batchnumtriangles = batchnumtriangles;
8410         }
8411
8412         // q1bsp surfaces rendered in vertex color mode have to have colors
8413         // calculated based on lightstyles
8414         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8415         {
8416                 // generate color arrays for the surfaces in this list
8417                 int c[4];
8418                 int scale;
8419                 int size3;
8420                 const int *offsets;
8421                 const unsigned char *lm;
8422                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8423                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8424                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8425                 numvertices = 0;
8426                 for (i = 0;i < texturenumsurfaces;i++)
8427                 {
8428                         surface = texturesurfacelist[i];
8429                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8430                         surfacenumvertices = surface->num_vertices;
8431                         if (surface->lightmapinfo->samples)
8432                         {
8433                                 for (j = 0;j < surfacenumvertices;j++)
8434                                 {
8435                                         lm = surface->lightmapinfo->samples + offsets[j];
8436                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8437                                         VectorScale(lm, scale, c);
8438                                         if (surface->lightmapinfo->styles[1] != 255)
8439                                         {
8440                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8441                                                 lm += size3;
8442                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8443                                                 VectorMA(c, scale, lm, c);
8444                                                 if (surface->lightmapinfo->styles[2] != 255)
8445                                                 {
8446                                                         lm += size3;
8447                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8448                                                         VectorMA(c, scale, lm, c);
8449                                                         if (surface->lightmapinfo->styles[3] != 255)
8450                                                         {
8451                                                                 lm += size3;
8452                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8453                                                                 VectorMA(c, scale, lm, c);
8454                                                         }
8455                                                 }
8456                                         }
8457                                         c[0] >>= 7;
8458                                         c[1] >>= 7;
8459                                         c[2] >>= 7;
8460                                         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);
8461                                         numvertices++;
8462                                 }
8463                         }
8464                         else
8465                         {
8466                                 for (j = 0;j < surfacenumvertices;j++)
8467                                 {
8468                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8469                                         numvertices++;
8470                                 }
8471                         }
8472                 }
8473         }
8474
8475         // if vertices are deformed (sprite flares and things in maps, possibly
8476         // water waves, bulges and other deformations), modify the copied vertices
8477         // in place
8478         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8479         {
8480                 switch (deform->deform)
8481                 {
8482                 default:
8483                 case Q3DEFORM_PROJECTIONSHADOW:
8484                 case Q3DEFORM_TEXT0:
8485                 case Q3DEFORM_TEXT1:
8486                 case Q3DEFORM_TEXT2:
8487                 case Q3DEFORM_TEXT3:
8488                 case Q3DEFORM_TEXT4:
8489                 case Q3DEFORM_TEXT5:
8490                 case Q3DEFORM_TEXT6:
8491                 case Q3DEFORM_TEXT7:
8492                 case Q3DEFORM_NONE:
8493                         break;
8494                 case Q3DEFORM_AUTOSPRITE:
8495                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8496                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8497                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8498                         VectorNormalize(newforward);
8499                         VectorNormalize(newright);
8500                         VectorNormalize(newup);
8501 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8502 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8503 //                      rsurface.batchvertex3f_bufferoffset = 0;
8504 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8505 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8506 //                      rsurface.batchsvector3f_bufferoffset = 0;
8507 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8508 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8509 //                      rsurface.batchtvector3f_bufferoffset = 0;
8510 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8511 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8512 //                      rsurface.batchnormal3f_bufferoffset = 0;
8513                         // a single autosprite surface can contain multiple sprites...
8514                         for (j = 0;j < batchnumvertices - 3;j += 4)
8515                         {
8516                                 VectorClear(center);
8517                                 for (i = 0;i < 4;i++)
8518                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8519                                 VectorScale(center, 0.25f, center);
8520                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8521                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8522                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8523                                 for (i = 0;i < 4;i++)
8524                                 {
8525                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8526                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8527                                 }
8528                         }
8529                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8530                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8531                         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);
8532                         break;
8533                 case Q3DEFORM_AUTOSPRITE2:
8534                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8535                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8536                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8537                         VectorNormalize(newforward);
8538                         VectorNormalize(newright);
8539                         VectorNormalize(newup);
8540 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8541 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8542 //                      rsurface.batchvertex3f_bufferoffset = 0;
8543                         {
8544                                 const float *v1, *v2;
8545                                 vec3_t start, end;
8546                                 float f, l;
8547                                 struct
8548                                 {
8549                                         float length2;
8550                                         const float *v1;
8551                                         const float *v2;
8552                                 }
8553                                 shortest[2];
8554                                 memset(shortest, 0, sizeof(shortest));
8555                                 // a single autosprite surface can contain multiple sprites...
8556                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8557                                 {
8558                                         VectorClear(center);
8559                                         for (i = 0;i < 4;i++)
8560                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8561                                         VectorScale(center, 0.25f, center);
8562                                         // find the two shortest edges, then use them to define the
8563                                         // axis vectors for rotating around the central axis
8564                                         for (i = 0;i < 6;i++)
8565                                         {
8566                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8567                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8568                                                 l = VectorDistance2(v1, v2);
8569                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8570                                                 if (v1[2] != v2[2])
8571                                                         l += (1.0f / 1024.0f);
8572                                                 if (shortest[0].length2 > l || i == 0)
8573                                                 {
8574                                                         shortest[1] = shortest[0];
8575                                                         shortest[0].length2 = l;
8576                                                         shortest[0].v1 = v1;
8577                                                         shortest[0].v2 = v2;
8578                                                 }
8579                                                 else if (shortest[1].length2 > l || i == 1)
8580                                                 {
8581                                                         shortest[1].length2 = l;
8582                                                         shortest[1].v1 = v1;
8583                                                         shortest[1].v2 = v2;
8584                                                 }
8585                                         }
8586                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8587                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8588                                         // this calculates the right vector from the shortest edge
8589                                         // and the up vector from the edge midpoints
8590                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8591                                         VectorNormalize(right);
8592                                         VectorSubtract(end, start, up);
8593                                         VectorNormalize(up);
8594                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8595                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8596                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8597                                         VectorNegate(forward, forward);
8598                                         VectorReflect(forward, 0, up, forward);
8599                                         VectorNormalize(forward);
8600                                         CrossProduct(up, forward, newright);
8601                                         VectorNormalize(newright);
8602                                         // rotate the quad around the up axis vector, this is made
8603                                         // especially easy by the fact we know the quad is flat,
8604                                         // so we only have to subtract the center position and
8605                                         // measure distance along the right vector, and then
8606                                         // multiply that by the newright vector and add back the
8607                                         // center position
8608                                         // we also need to subtract the old position to undo the
8609                                         // displacement from the center, which we do with a
8610                                         // DotProduct, the subtraction/addition of center is also
8611                                         // optimized into DotProducts here
8612                                         l = DotProduct(right, center);
8613                                         for (i = 0;i < 4;i++)
8614                                         {
8615                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8616                                                 f = DotProduct(right, v1) - l;
8617                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8618                                         }
8619                                 }
8620                         }
8621                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8622                         {
8623 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8624 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8625 //                              rsurface.batchnormal3f_bufferoffset = 0;
8626                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8627                         }
8628                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8629                         {
8630 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8631 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8632 //                              rsurface.batchsvector3f_bufferoffset = 0;
8633 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8634 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8635 //                              rsurface.batchtvector3f_bufferoffset = 0;
8636                                 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);
8637                         }
8638                         break;
8639                 case Q3DEFORM_NORMAL:
8640                         // deform the normals to make reflections wavey
8641                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8642                         rsurface.batchnormal3f_vertexbuffer = NULL;
8643                         rsurface.batchnormal3f_bufferoffset = 0;
8644                         for (j = 0;j < batchnumvertices;j++)
8645                         {
8646                                 float vertex[3];
8647                                 float *normal = rsurface.batchnormal3f + 3*j;
8648                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8649                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8650                                 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]);
8651                                 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]);
8652                                 VectorNormalize(normal);
8653                         }
8654                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8655                         {
8656 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8657 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8658 //                              rsurface.batchsvector3f_bufferoffset = 0;
8659 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8660 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8661 //                              rsurface.batchtvector3f_bufferoffset = 0;
8662                                 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);
8663                         }
8664                         break;
8665                 case Q3DEFORM_WAVE:
8666                         // deform vertex array to make wavey water and flags and such
8667                         waveparms[0] = deform->waveparms[0];
8668                         waveparms[1] = deform->waveparms[1];
8669                         waveparms[2] = deform->waveparms[2];
8670                         waveparms[3] = deform->waveparms[3];
8671                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8672                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8673                         // this is how a divisor of vertex influence on deformation
8674                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8675                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8676 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8677 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8678 //                      rsurface.batchvertex3f_bufferoffset = 0;
8679 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8680 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8681 //                      rsurface.batchnormal3f_bufferoffset = 0;
8682                         for (j = 0;j < batchnumvertices;j++)
8683                         {
8684                                 // if the wavefunc depends on time, evaluate it per-vertex
8685                                 if (waveparms[3])
8686                                 {
8687                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8688                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8689                                 }
8690                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8691                         }
8692                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8693                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8694                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8695                         {
8696 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8697 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8698 //                              rsurface.batchsvector3f_bufferoffset = 0;
8699 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8700 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8701 //                              rsurface.batchtvector3f_bufferoffset = 0;
8702                                 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);
8703                         }
8704                         break;
8705                 case Q3DEFORM_BULGE:
8706                         // deform vertex array to make the surface have moving bulges
8707 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8708 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8709 //                      rsurface.batchvertex3f_bufferoffset = 0;
8710 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8711 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8712 //                      rsurface.batchnormal3f_bufferoffset = 0;
8713                         for (j = 0;j < batchnumvertices;j++)
8714                         {
8715                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8716                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8717                         }
8718                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8719                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8720                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8721                         {
8722 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8723 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8724 //                              rsurface.batchsvector3f_bufferoffset = 0;
8725 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8726 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8727 //                              rsurface.batchtvector3f_bufferoffset = 0;
8728                                 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);
8729                         }
8730                         break;
8731                 case Q3DEFORM_MOVE:
8732                         // deform vertex array
8733                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8734                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8735                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8736                         VectorScale(deform->parms, scale, waveparms);
8737 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8738 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8739 //                      rsurface.batchvertex3f_bufferoffset = 0;
8740                         for (j = 0;j < batchnumvertices;j++)
8741                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8742                         break;
8743                 }
8744         }
8745
8746         // generate texcoords based on the chosen texcoord source
8747         switch(rsurface.texture->tcgen.tcgen)
8748         {
8749         default:
8750         case Q3TCGEN_TEXTURE:
8751                 break;
8752         case Q3TCGEN_LIGHTMAP:
8753 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8754 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8755 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8756                 if (rsurface.batchtexcoordlightmap2f)
8757                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8758                 break;
8759         case Q3TCGEN_VECTOR:
8760 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8761 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8762 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8763                 for (j = 0;j < batchnumvertices;j++)
8764                 {
8765                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8766                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8767                 }
8768                 break;
8769         case Q3TCGEN_ENVIRONMENT:
8770                 // make environment reflections using a spheremap
8771                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8772                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8773                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8774                 for (j = 0;j < batchnumvertices;j++)
8775                 {
8776                         // identical to Q3A's method, but executed in worldspace so
8777                         // carried models can be shiny too
8778
8779                         float viewer[3], d, reflected[3], worldreflected[3];
8780
8781                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8782                         // VectorNormalize(viewer);
8783
8784                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8785
8786                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8787                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8788                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8789                         // note: this is proportinal to viewer, so we can normalize later
8790
8791                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8792                         VectorNormalize(worldreflected);
8793
8794                         // note: this sphere map only uses world x and z!
8795                         // so positive and negative y will LOOK THE SAME.
8796                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8797                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8798                 }
8799                 break;
8800         }
8801         // the only tcmod that needs software vertex processing is turbulent, so
8802         // check for it here and apply the changes if needed
8803         // and we only support that as the first one
8804         // (handling a mixture of turbulent and other tcmods would be problematic
8805         //  without punting it entirely to a software path)
8806         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8807         {
8808                 amplitude = rsurface.texture->tcmods[0].parms[1];
8809                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8810 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8811 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8812 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8813                 for (j = 0;j < batchnumvertices;j++)
8814                 {
8815                         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);
8816                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8817                 }
8818         }
8819
8820         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8821         {
8822                 // convert the modified arrays to vertex structs
8823 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8824 //              rsurface.batchvertexmeshbuffer = NULL;
8825                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8826                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8827                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8828                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8829                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8830                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8831                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8832                 {
8833                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8834                         {
8835                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8836                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8837                         }
8838                 }
8839                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8840                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8841                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8842                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8843                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8844                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8845                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8846                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8847                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8848         }
8849 }
8850
8851 void RSurf_DrawBatch(void)
8852 {
8853         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8854         // through the pipeline, killing it earlier in the pipeline would have
8855         // per-surface overhead rather than per-batch overhead, so it's best to
8856         // reject it here, before it hits glDraw.
8857         if (rsurface.batchnumtriangles == 0)
8858                 return;
8859 #if 0
8860         // batch debugging code
8861         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8862         {
8863                 int i;
8864                 int j;
8865                 int c;
8866                 const int *e;
8867                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8868                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8869                 {
8870                         c = e[i];
8871                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8872                         {
8873                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8874                                 {
8875                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8876                                                 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);
8877                                         break;
8878                                 }
8879                         }
8880                 }
8881         }
8882 #endif
8883         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);
8884 }
8885
8886 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8887 {
8888         // pick the closest matching water plane
8889         int planeindex, vertexindex, bestplaneindex = -1;
8890         float d, bestd;
8891         vec3_t vert;
8892         const float *v;
8893         r_waterstate_waterplane_t *p;
8894         qboolean prepared = false;
8895         bestd = 0;
8896         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8897         {
8898                 if(p->camera_entity != rsurface.texture->camera_entity)
8899                         continue;
8900                 d = 0;
8901                 if(!prepared)
8902                 {
8903                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8904                         prepared = true;
8905                         if(rsurface.batchnumvertices == 0)
8906                                 break;
8907                 }
8908                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8909                 {
8910                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8911                         d += fabs(PlaneDiff(vert, &p->plane));
8912                 }
8913                 if (bestd > d || bestplaneindex < 0)
8914                 {
8915                         bestd = d;
8916                         bestplaneindex = planeindex;
8917                 }
8918         }
8919         return bestplaneindex;
8920         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8921         // this situation though, as it might be better to render single larger
8922         // batches with useless stuff (backface culled for example) than to
8923         // render multiple smaller batches
8924 }
8925
8926 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8927 {
8928         int i;
8929         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8930         rsurface.passcolor4f_vertexbuffer = 0;
8931         rsurface.passcolor4f_bufferoffset = 0;
8932         for (i = 0;i < rsurface.batchnumvertices;i++)
8933                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8934 }
8935
8936 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8937 {
8938         int i;
8939         float f;
8940         const float *v;
8941         const float *c;
8942         float *c2;
8943         if (rsurface.passcolor4f)
8944         {
8945                 // generate color arrays
8946                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8947                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8948                 rsurface.passcolor4f_vertexbuffer = 0;
8949                 rsurface.passcolor4f_bufferoffset = 0;
8950                 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)
8951                 {
8952                         f = RSurf_FogVertex(v);
8953                         c2[0] = c[0] * f;
8954                         c2[1] = c[1] * f;
8955                         c2[2] = c[2] * f;
8956                         c2[3] = c[3];
8957                 }
8958         }
8959         else
8960         {
8961                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8962                 rsurface.passcolor4f_vertexbuffer = 0;
8963                 rsurface.passcolor4f_bufferoffset = 0;
8964                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8965                 {
8966                         f = RSurf_FogVertex(v);
8967                         c2[0] = f;
8968                         c2[1] = f;
8969                         c2[2] = f;
8970                         c2[3] = 1;
8971                 }
8972         }
8973 }
8974
8975 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8976 {
8977         int i;
8978         float f;
8979         const float *v;
8980         const float *c;
8981         float *c2;
8982         if (!rsurface.passcolor4f)
8983                 return;
8984         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8985         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8986         rsurface.passcolor4f_vertexbuffer = 0;
8987         rsurface.passcolor4f_bufferoffset = 0;
8988         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)
8989         {
8990                 f = RSurf_FogVertex(v);
8991                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8992                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8993                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8994                 c2[3] = c[3];
8995         }
8996 }
8997
8998 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
8999 {
9000         int i;
9001         const float *c;
9002         float *c2;
9003         if (!rsurface.passcolor4f)
9004                 return;
9005         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9006         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9007         rsurface.passcolor4f_vertexbuffer = 0;
9008         rsurface.passcolor4f_bufferoffset = 0;
9009         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9010         {
9011                 c2[0] = c[0] * r;
9012                 c2[1] = c[1] * g;
9013                 c2[2] = c[2] * b;
9014                 c2[3] = c[3] * a;
9015         }
9016 }
9017
9018 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9019 {
9020         int i;
9021         const float *c;
9022         float *c2;
9023         if (!rsurface.passcolor4f)
9024                 return;
9025         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9026         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9027         rsurface.passcolor4f_vertexbuffer = 0;
9028         rsurface.passcolor4f_bufferoffset = 0;
9029         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9030         {
9031                 c2[0] = c[0] + r_refdef.scene.ambient;
9032                 c2[1] = c[1] + r_refdef.scene.ambient;
9033                 c2[2] = c[2] + r_refdef.scene.ambient;
9034                 c2[3] = c[3];
9035         }
9036 }
9037
9038 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9039 {
9040         // TODO: optimize
9041         rsurface.passcolor4f = NULL;
9042         rsurface.passcolor4f_vertexbuffer = 0;
9043         rsurface.passcolor4f_bufferoffset = 0;
9044         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9045         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9046         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9047         GL_Color(r, g, b, a);
9048         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9049         RSurf_DrawBatch();
9050 }
9051
9052 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9053 {
9054         // TODO: optimize applyfog && applycolor case
9055         // just apply fog if necessary, and tint the fog color array if necessary
9056         rsurface.passcolor4f = NULL;
9057         rsurface.passcolor4f_vertexbuffer = 0;
9058         rsurface.passcolor4f_bufferoffset = 0;
9059         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9060         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9061         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9062         GL_Color(r, g, b, a);
9063         RSurf_DrawBatch();
9064 }
9065
9066 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9067 {
9068         // TODO: optimize
9069         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9070         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9071         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9072         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9073         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9074         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9075         GL_Color(r, g, b, a);
9076         RSurf_DrawBatch();
9077 }
9078
9079 static void RSurf_DrawBatch_GL11_ClampColor(void)
9080 {
9081         int i;
9082         const float *c1;
9083         float *c2;
9084         if (!rsurface.passcolor4f)
9085                 return;
9086         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9087         {
9088                 c2[0] = bound(0.0f, c1[0], 1.0f);
9089                 c2[1] = bound(0.0f, c1[1], 1.0f);
9090                 c2[2] = bound(0.0f, c1[2], 1.0f);
9091                 c2[3] = bound(0.0f, c1[3], 1.0f);
9092         }
9093 }
9094
9095 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9096 {
9097         int i;
9098         float f;
9099         const float *v;
9100         const float *n;
9101         float *c;
9102         //vec3_t eyedir;
9103
9104         // fake shading
9105         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9106         rsurface.passcolor4f_vertexbuffer = 0;
9107         rsurface.passcolor4f_bufferoffset = 0;
9108         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)
9109         {
9110                 f = -DotProduct(r_refdef.view.forward, n);
9111                 f = max(0, f);
9112                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9113                 f *= r_refdef.lightmapintensity;
9114                 Vector4Set(c, f, f, f, 1);
9115         }
9116 }
9117
9118 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9119 {
9120         RSurf_DrawBatch_GL11_ApplyFakeLight();
9121         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9122         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9123         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9124         GL_Color(r, g, b, a);
9125         RSurf_DrawBatch();
9126 }
9127
9128 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9129 {
9130         int i;
9131         float f;
9132         float alpha;
9133         const float *v;
9134         const float *n;
9135         float *c;
9136         vec3_t ambientcolor;
9137         vec3_t diffusecolor;
9138         vec3_t lightdir;
9139         // TODO: optimize
9140         // model lighting
9141         VectorCopy(rsurface.modellight_lightdir, lightdir);
9142         f = 0.5f * r_refdef.lightmapintensity;
9143         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9144         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9145         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9146         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9147         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9148         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9149         alpha = *a;
9150         if (VectorLength2(diffusecolor) > 0)
9151         {
9152                 // q3-style directional shading
9153                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9154                 rsurface.passcolor4f_vertexbuffer = 0;
9155                 rsurface.passcolor4f_bufferoffset = 0;
9156                 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)
9157                 {
9158                         if ((f = DotProduct(n, lightdir)) > 0)
9159                                 VectorMA(ambientcolor, f, diffusecolor, c);
9160                         else
9161                                 VectorCopy(ambientcolor, c);
9162                         c[3] = alpha;
9163                 }
9164                 *r = 1;
9165                 *g = 1;
9166                 *b = 1;
9167                 *a = 1;
9168                 *applycolor = false;
9169         }
9170         else
9171         {
9172                 *r = ambientcolor[0];
9173                 *g = ambientcolor[1];
9174                 *b = ambientcolor[2];
9175                 rsurface.passcolor4f = NULL;
9176                 rsurface.passcolor4f_vertexbuffer = 0;
9177                 rsurface.passcolor4f_bufferoffset = 0;
9178         }
9179 }
9180
9181 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9182 {
9183         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9184         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9185         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9186         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9187         GL_Color(r, g, b, a);
9188         RSurf_DrawBatch();
9189 }
9190
9191 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9192 {
9193         int i;
9194         float f;
9195         const float *v;
9196         float *c;
9197         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9198         {
9199                 f = 1 - RSurf_FogVertex(v);
9200                 c[0] = r;
9201                 c[1] = g;
9202                 c[2] = b;
9203                 c[3] = f * a;
9204         }
9205 }
9206
9207 void RSurf_SetupDepthAndCulling(void)
9208 {
9209         // submodels are biased to avoid z-fighting with world surfaces that they
9210         // may be exactly overlapping (avoids z-fighting artifacts on certain
9211         // doors and things in Quake maps)
9212         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9213         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9214         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9215         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9216 }
9217
9218 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9219 {
9220         // transparent sky would be ridiculous
9221         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9222                 return;
9223         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9224         skyrenderlater = true;
9225         RSurf_SetupDepthAndCulling();
9226         GL_DepthMask(true);
9227         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9228         // skymasking on them, and Quake3 never did sky masking (unlike
9229         // software Quake and software Quake2), so disable the sky masking
9230         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9231         // and skymasking also looks very bad when noclipping outside the
9232         // level, so don't use it then either.
9233         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9234         {
9235                 R_Mesh_ResetTextureState();
9236                 if (skyrendermasked)
9237                 {
9238                         R_SetupShader_DepthOrShadow();
9239                         // depth-only (masking)
9240                         GL_ColorMask(0,0,0,0);
9241                         // just to make sure that braindead drivers don't draw
9242                         // anything despite that colormask...
9243                         GL_BlendFunc(GL_ZERO, GL_ONE);
9244                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9245                         if (rsurface.batchvertex3fbuffer)
9246                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9247                         else
9248                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9249                 }
9250                 else
9251                 {
9252                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9253                         // fog sky
9254                         GL_BlendFunc(GL_ONE, GL_ZERO);
9255                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9256                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9257                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9258                 }
9259                 RSurf_DrawBatch();
9260                 if (skyrendermasked)
9261                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9262         }
9263         R_Mesh_ResetTextureState();
9264         GL_Color(1, 1, 1, 1);
9265 }
9266
9267 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9268 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9269 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9270 {
9271         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9272                 return;
9273         if (prepass)
9274         {
9275                 // render screenspace normalmap to texture
9276                 GL_DepthMask(true);
9277                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9278                 RSurf_DrawBatch();
9279                 return;
9280         }
9281
9282         // bind lightmap texture
9283
9284         // water/refraction/reflection/camera surfaces have to be handled specially
9285         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9286         {
9287                 int start, end, startplaneindex;
9288                 for (start = 0;start < texturenumsurfaces;start = end)
9289                 {
9290                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9291                         if(startplaneindex < 0)
9292                         {
9293                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9294                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9295                                 end = start + 1;
9296                                 continue;
9297                         }
9298                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9299                                 ;
9300                         // now that we have a batch using the same planeindex, render it
9301                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9302                         {
9303                                 // render water or distortion background
9304                                 GL_DepthMask(true);
9305                                 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));
9306                                 RSurf_DrawBatch();
9307                                 // blend surface on top
9308                                 GL_DepthMask(false);
9309                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9310                                 RSurf_DrawBatch();
9311                         }
9312                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9313                         {
9314                                 // render surface with reflection texture as input
9315                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9316                                 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));
9317                                 RSurf_DrawBatch();
9318                         }
9319                 }
9320                 return;
9321         }
9322
9323         // render surface batch normally
9324         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9325         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9326         RSurf_DrawBatch();
9327 }
9328
9329 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9330 {
9331         // OpenGL 1.3 path - anything not completely ancient
9332         qboolean applycolor;
9333         qboolean applyfog;
9334         int layerindex;
9335         const texturelayer_t *layer;
9336         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);
9337         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9338
9339         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9340         {
9341                 vec4_t layercolor;
9342                 int layertexrgbscale;
9343                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9344                 {
9345                         if (layerindex == 0)
9346                                 GL_AlphaTest(true);
9347                         else
9348                         {
9349                                 GL_AlphaTest(false);
9350                                 GL_DepthFunc(GL_EQUAL);
9351                         }
9352                 }
9353                 GL_DepthMask(layer->depthmask && writedepth);
9354                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9355                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9356                 {
9357                         layertexrgbscale = 4;
9358                         VectorScale(layer->color, 0.25f, layercolor);
9359                 }
9360                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9361                 {
9362                         layertexrgbscale = 2;
9363                         VectorScale(layer->color, 0.5f, layercolor);
9364                 }
9365                 else
9366                 {
9367                         layertexrgbscale = 1;
9368                         VectorScale(layer->color, 1.0f, layercolor);
9369                 }
9370                 layercolor[3] = layer->color[3];
9371                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9372                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9373                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9374                 switch (layer->type)
9375                 {
9376                 case TEXTURELAYERTYPE_LITTEXTURE:
9377                         // single-pass lightmapped texture with 2x rgbscale
9378                         R_Mesh_TexBind(0, r_texture_white);
9379                         R_Mesh_TexMatrix(0, NULL);
9380                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9381                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9382                         R_Mesh_TexBind(1, layer->texture);
9383                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9384                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9385                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9386                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9387                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9388                         else if (FAKELIGHT_ENABLED)
9389                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9390                         else if (rsurface.uselightmaptexture)
9391                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9392                         else
9393                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9394                         break;
9395                 case TEXTURELAYERTYPE_TEXTURE:
9396                         // singletexture unlit texture with transparency support
9397                         R_Mesh_TexBind(0, layer->texture);
9398                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9399                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9400                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9401                         R_Mesh_TexBind(1, 0);
9402                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9403                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9404                         break;
9405                 case TEXTURELAYERTYPE_FOG:
9406                         // singletexture fogging
9407                         if (layer->texture)
9408                         {
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                         }
9414                         else
9415                         {
9416                                 R_Mesh_TexBind(0, 0);
9417                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9418                         }
9419                         R_Mesh_TexBind(1, 0);
9420                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9421                         // generate a color array for the fog pass
9422                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9423                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9424                         RSurf_DrawBatch();
9425                         break;
9426                 default:
9427                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9428                 }
9429         }
9430         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9431         {
9432                 GL_DepthFunc(GL_LEQUAL);
9433                 GL_AlphaTest(false);
9434         }
9435 }
9436
9437 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9438 {
9439         // OpenGL 1.1 - crusty old voodoo path
9440         qboolean applyfog;
9441         int layerindex;
9442         const texturelayer_t *layer;
9443         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);
9444         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9445
9446         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9447         {
9448                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9449                 {
9450                         if (layerindex == 0)
9451                                 GL_AlphaTest(true);
9452                         else
9453                         {
9454                                 GL_AlphaTest(false);
9455                                 GL_DepthFunc(GL_EQUAL);
9456                         }
9457                 }
9458                 GL_DepthMask(layer->depthmask && writedepth);
9459                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9460                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9461                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9462                 switch (layer->type)
9463                 {
9464                 case TEXTURELAYERTYPE_LITTEXTURE:
9465                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9466                         {
9467                                 // two-pass lit texture with 2x rgbscale
9468                                 // first the lightmap pass
9469                                 R_Mesh_TexBind(0, r_texture_white);
9470                                 R_Mesh_TexMatrix(0, NULL);
9471                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9472                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9473                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9474                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9475                                 else if (FAKELIGHT_ENABLED)
9476                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9477                                 else if (rsurface.uselightmaptexture)
9478                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9479                                 else
9480                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9481                                 // then apply the texture to it
9482                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9483                                 R_Mesh_TexBind(0, layer->texture);
9484                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9485                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9486                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9487                                 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);
9488                         }
9489                         else
9490                         {
9491                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9492                                 R_Mesh_TexBind(0, layer->texture);
9493                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9494                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9495                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9496                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9497                                         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);
9498                                 else
9499                                         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);
9500                         }
9501                         break;
9502                 case TEXTURELAYERTYPE_TEXTURE:
9503                         // singletexture unlit texture with 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                         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);
9509                         break;
9510                 case TEXTURELAYERTYPE_FOG:
9511                         // singletexture fogging
9512                         if (layer->texture)
9513                         {
9514                                 R_Mesh_TexBind(0, layer->texture);
9515                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9516                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9517                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9518                         }
9519                         else
9520                         {
9521                                 R_Mesh_TexBind(0, 0);
9522                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9523                         }
9524                         // generate a color array for the fog pass
9525                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9526                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9527                         RSurf_DrawBatch();
9528                         break;
9529                 default:
9530                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9531                 }
9532         }
9533         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9534         {
9535                 GL_DepthFunc(GL_LEQUAL);
9536                 GL_AlphaTest(false);
9537         }
9538 }
9539
9540 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9541 {
9542         int vi;
9543         int j;
9544         r_vertexgeneric_t *batchvertex;
9545         float c[4];
9546
9547 //      R_Mesh_ResetTextureState();
9548         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9549
9550         if(rsurface.texture && rsurface.texture->currentskinframe)
9551         {
9552                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9553                 c[3] *= rsurface.texture->currentalpha;
9554         }
9555         else
9556         {
9557                 c[0] = 1;
9558                 c[1] = 0;
9559                 c[2] = 1;
9560                 c[3] = 1;
9561         }
9562
9563         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9564         {
9565                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9566                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9567                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9568         }
9569
9570         // brighten it up (as texture value 127 means "unlit")
9571         c[0] *= 2 * r_refdef.view.colorscale;
9572         c[1] *= 2 * r_refdef.view.colorscale;
9573         c[2] *= 2 * r_refdef.view.colorscale;
9574
9575         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9576                 c[3] *= r_wateralpha.value;
9577
9578         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9579         {
9580                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9581                 GL_DepthMask(false);
9582         }
9583         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9584         {
9585                 GL_BlendFunc(GL_ONE, GL_ONE);
9586                 GL_DepthMask(false);
9587         }
9588         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9589         {
9590                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9591                 GL_DepthMask(false);
9592         }
9593         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9594         {
9595                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9596                 GL_DepthMask(false);
9597         }
9598         else
9599         {
9600                 GL_BlendFunc(GL_ONE, GL_ZERO);
9601                 GL_DepthMask(writedepth);
9602         }
9603
9604         if (r_showsurfaces.integer == 3)
9605         {
9606                 rsurface.passcolor4f = NULL;
9607
9608                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9609                 {
9610                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9611
9612                         rsurface.passcolor4f = NULL;
9613                         rsurface.passcolor4f_vertexbuffer = 0;
9614                         rsurface.passcolor4f_bufferoffset = 0;
9615                 }
9616                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9617                 {
9618                         qboolean applycolor = true;
9619                         float one = 1.0;
9620
9621                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9622
9623                         r_refdef.lightmapintensity = 1;
9624                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9625                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9626                 }
9627                 else if (FAKELIGHT_ENABLED)
9628                 {
9629                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9630
9631                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9632                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9633                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9634                 }
9635                 else
9636                 {
9637                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9638
9639                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9640                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9641                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9642                 }
9643
9644                 if(!rsurface.passcolor4f)
9645                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9646
9647                 RSurf_DrawBatch_GL11_ApplyAmbient();
9648                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9649                 if(r_refdef.fogenabled)
9650                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9651                 RSurf_DrawBatch_GL11_ClampColor();
9652
9653                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9654                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9655                 RSurf_DrawBatch();
9656         }
9657         else if (!r_refdef.view.showdebug)
9658         {
9659                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9660                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9661                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9662                 {
9663                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9664                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9665                 }
9666                 R_Mesh_PrepareVertices_Generic_Unlock();
9667                 RSurf_DrawBatch();
9668         }
9669         else if (r_showsurfaces.integer == 4)
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                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9676                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9677                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9678                 }
9679                 R_Mesh_PrepareVertices_Generic_Unlock();
9680                 RSurf_DrawBatch();
9681         }
9682         else if (r_showsurfaces.integer == 2)
9683         {
9684                 const int *e;
9685                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9686                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9687                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9688                 {
9689                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9690                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9691                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9692                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9693                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9694                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9695                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9696                 }
9697                 R_Mesh_PrepareVertices_Generic_Unlock();
9698                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9699         }
9700         else
9701         {
9702                 int texturesurfaceindex;
9703                 int k;
9704                 const msurface_t *surface;
9705                 float surfacecolor4f[4];
9706                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9707                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9708                 vi = 0;
9709                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9710                 {
9711                         surface = texturesurfacelist[texturesurfaceindex];
9712                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9713                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9714                         for (j = 0;j < surface->num_vertices;j++)
9715                         {
9716                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9717                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9718                                 vi++;
9719                         }
9720                 }
9721                 R_Mesh_PrepareVertices_Generic_Unlock();
9722                 RSurf_DrawBatch();
9723         }
9724 }
9725
9726 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9727 {
9728         CHECKGLERROR
9729         RSurf_SetupDepthAndCulling();
9730         if (r_showsurfaces.integer)
9731         {
9732                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9733                 return;
9734         }
9735         switch (vid.renderpath)
9736         {
9737         case RENDERPATH_GL20:
9738         case RENDERPATH_D3D9:
9739         case RENDERPATH_D3D10:
9740         case RENDERPATH_D3D11:
9741         case RENDERPATH_SOFT:
9742         case RENDERPATH_GLES2:
9743                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9744                 break;
9745         case RENDERPATH_GL13:
9746                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9747                 break;
9748         case RENDERPATH_GL11:
9749                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9750                 break;
9751         }
9752         CHECKGLERROR
9753 }
9754
9755 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9756 {
9757         CHECKGLERROR
9758         RSurf_SetupDepthAndCulling();
9759         if (r_showsurfaces.integer)
9760         {
9761                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9762                 return;
9763         }
9764         switch (vid.renderpath)
9765         {
9766         case RENDERPATH_GL20:
9767         case RENDERPATH_D3D9:
9768         case RENDERPATH_D3D10:
9769         case RENDERPATH_D3D11:
9770         case RENDERPATH_SOFT:
9771         case RENDERPATH_GLES2:
9772                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9773                 break;
9774         case RENDERPATH_GL13:
9775                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9776                 break;
9777         case RENDERPATH_GL11:
9778                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9779                 break;
9780         }
9781         CHECKGLERROR
9782 }
9783
9784 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9785 {
9786         int i, j;
9787         int texturenumsurfaces, endsurface;
9788         texture_t *texture;
9789         const msurface_t *surface;
9790 #define MAXBATCH_TRANSPARENTSURFACES 256
9791         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9792
9793         // if the model is static it doesn't matter what value we give for
9794         // wantnormals and wanttangents, so this logic uses only rules applicable
9795         // to a model, knowing that they are meaningless otherwise
9796         if (ent == r_refdef.scene.worldentity)
9797                 RSurf_ActiveWorldEntity();
9798         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9799                 RSurf_ActiveModelEntity(ent, false, false, false);
9800         else
9801         {
9802                 switch (vid.renderpath)
9803                 {
9804                 case RENDERPATH_GL20:
9805                 case RENDERPATH_D3D9:
9806                 case RENDERPATH_D3D10:
9807                 case RENDERPATH_D3D11:
9808                 case RENDERPATH_SOFT:
9809                 case RENDERPATH_GLES2:
9810                         RSurf_ActiveModelEntity(ent, true, true, false);
9811                         break;
9812                 case RENDERPATH_GL13:
9813                 case RENDERPATH_GL11:
9814                         RSurf_ActiveModelEntity(ent, true, false, false);
9815                         break;
9816                 }
9817         }
9818
9819         if (r_transparentdepthmasking.integer)
9820         {
9821                 qboolean setup = false;
9822                 for (i = 0;i < numsurfaces;i = j)
9823                 {
9824                         j = i + 1;
9825                         surface = rsurface.modelsurfaces + surfacelist[i];
9826                         texture = surface->texture;
9827                         rsurface.texture = R_GetCurrentTexture(texture);
9828                         rsurface.lightmaptexture = NULL;
9829                         rsurface.deluxemaptexture = NULL;
9830                         rsurface.uselightmaptexture = false;
9831                         // scan ahead until we find a different texture
9832                         endsurface = min(i + 1024, numsurfaces);
9833                         texturenumsurfaces = 0;
9834                         texturesurfacelist[texturenumsurfaces++] = surface;
9835                         for (;j < endsurface;j++)
9836                         {
9837                                 surface = rsurface.modelsurfaces + surfacelist[j];
9838                                 if (texture != surface->texture)
9839                                         break;
9840                                 texturesurfacelist[texturenumsurfaces++] = surface;
9841                         }
9842                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9843                                 continue;
9844                         // render the range of surfaces as depth
9845                         if (!setup)
9846                         {
9847                                 setup = true;
9848                                 GL_ColorMask(0,0,0,0);
9849                                 GL_Color(1,1,1,1);
9850                                 GL_DepthTest(true);
9851                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9852                                 GL_DepthMask(true);
9853 //                              R_Mesh_ResetTextureState();
9854                                 R_SetupShader_DepthOrShadow();
9855                         }
9856                         RSurf_SetupDepthAndCulling();
9857                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9858                         if (rsurface.batchvertex3fbuffer)
9859                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9860                         else
9861                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9862                         RSurf_DrawBatch();
9863                 }
9864                 if (setup)
9865                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9866         }
9867
9868         for (i = 0;i < numsurfaces;i = j)
9869         {
9870                 j = i + 1;
9871                 surface = rsurface.modelsurfaces + surfacelist[i];
9872                 texture = surface->texture;
9873                 rsurface.texture = R_GetCurrentTexture(texture);
9874                 // scan ahead until we find a different texture
9875                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9876                 texturenumsurfaces = 0;
9877                 texturesurfacelist[texturenumsurfaces++] = surface;
9878                 if(FAKELIGHT_ENABLED)
9879                 {
9880                         rsurface.lightmaptexture = NULL;
9881                         rsurface.deluxemaptexture = NULL;
9882                         rsurface.uselightmaptexture = false;
9883                         for (;j < endsurface;j++)
9884                         {
9885                                 surface = rsurface.modelsurfaces + surfacelist[j];
9886                                 if (texture != surface->texture)
9887                                         break;
9888                                 texturesurfacelist[texturenumsurfaces++] = surface;
9889                         }
9890                 }
9891                 else
9892                 {
9893                         rsurface.lightmaptexture = surface->lightmaptexture;
9894                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9895                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9896                         for (;j < endsurface;j++)
9897                         {
9898                                 surface = rsurface.modelsurfaces + surfacelist[j];
9899                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9900                                         break;
9901                                 texturesurfacelist[texturenumsurfaces++] = surface;
9902                         }
9903                 }
9904                 // render the range of surfaces
9905                 if (ent == r_refdef.scene.worldentity)
9906                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9907                 else
9908                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9909         }
9910         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9911 }
9912
9913 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9914 {
9915         // transparent surfaces get pushed off into the transparent queue
9916         int surfacelistindex;
9917         const msurface_t *surface;
9918         vec3_t tempcenter, center;
9919         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9920         {
9921                 surface = texturesurfacelist[surfacelistindex];
9922                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9923                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9924                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9925                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9926                 if (queueentity->transparent_offset) // transparent offset
9927                 {
9928                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9929                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9930                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9931                 }
9932                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9933         }
9934 }
9935
9936 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9937 {
9938         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9939                 return;
9940         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9941                 return;
9942         RSurf_SetupDepthAndCulling();
9943         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9944         if (rsurface.batchvertex3fbuffer)
9945                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9946         else
9947                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9948         RSurf_DrawBatch();
9949 }
9950
9951 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9952 {
9953         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9954         CHECKGLERROR
9955         if (depthonly)
9956                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9957         else if (prepass)
9958         {
9959                 if (!rsurface.texture->currentnumlayers)
9960                         return;
9961                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9962                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9963                 else
9964                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9965         }
9966         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9967                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9968         else if (!rsurface.texture->currentnumlayers)
9969                 return;
9970         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9971         {
9972                 // in the deferred case, transparent surfaces were queued during prepass
9973                 if (!r_shadow_usingdeferredprepass)
9974                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9975         }
9976         else
9977         {
9978                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9979                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9980         }
9981         CHECKGLERROR
9982 }
9983
9984 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9985 {
9986         int i, j;
9987         texture_t *texture;
9988         R_FrameData_SetMark();
9989         // break the surface list down into batches by texture and use of lightmapping
9990         for (i = 0;i < numsurfaces;i = j)
9991         {
9992                 j = i + 1;
9993                 // texture is the base texture pointer, rsurface.texture is the
9994                 // current frame/skin the texture is directing us to use (for example
9995                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9996                 // use skin 1 instead)
9997                 texture = surfacelist[i]->texture;
9998                 rsurface.texture = R_GetCurrentTexture(texture);
9999                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10000                 {
10001                         // if this texture is not the kind we want, skip ahead to the next one
10002                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10003                                 ;
10004                         continue;
10005                 }
10006                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10007                 {
10008                         rsurface.lightmaptexture = NULL;
10009                         rsurface.deluxemaptexture = NULL;
10010                         rsurface.uselightmaptexture = false;
10011                         // simply scan ahead until we find a different texture or lightmap state
10012                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10013                                 ;
10014                 }
10015                 else
10016                 {
10017                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10018                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10019                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10020                         // simply scan ahead until we find a different texture or lightmap state
10021                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10022                                 ;
10023                 }
10024                 // render the range of surfaces
10025                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10026         }
10027         R_FrameData_ReturnToMark();
10028 }
10029
10030 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10031 {
10032         CHECKGLERROR
10033         if (depthonly)
10034                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10035         else if (prepass)
10036         {
10037                 if (!rsurface.texture->currentnumlayers)
10038                         return;
10039                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10040                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10041                 else
10042                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10043         }
10044         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10045                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10046         else if (!rsurface.texture->currentnumlayers)
10047                 return;
10048         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10049         {
10050                 // in the deferred case, transparent surfaces were queued during prepass
10051                 if (!r_shadow_usingdeferredprepass)
10052                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10053         }
10054         else
10055         {
10056                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10057                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10058         }
10059         CHECKGLERROR
10060 }
10061
10062 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10063 {
10064         int i, j;
10065         texture_t *texture;
10066         R_FrameData_SetMark();
10067         // break the surface list down into batches by texture and use of lightmapping
10068         for (i = 0;i < numsurfaces;i = j)
10069         {
10070                 j = i + 1;
10071                 // texture is the base texture pointer, rsurface.texture is the
10072                 // current frame/skin the texture is directing us to use (for example
10073                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10074                 // use skin 1 instead)
10075                 texture = surfacelist[i]->texture;
10076                 rsurface.texture = R_GetCurrentTexture(texture);
10077                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10078                 {
10079                         // if this texture is not the kind we want, skip ahead to the next one
10080                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10081                                 ;
10082                         continue;
10083                 }
10084                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10085                 {
10086                         rsurface.lightmaptexture = NULL;
10087                         rsurface.deluxemaptexture = NULL;
10088                         rsurface.uselightmaptexture = false;
10089                         // simply scan ahead until we find a different texture or lightmap state
10090                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10091                                 ;
10092                 }
10093                 else
10094                 {
10095                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10096                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10097                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10098                         // simply scan ahead until we find a different texture or lightmap state
10099                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10100                                 ;
10101                 }
10102                 // render the range of surfaces
10103                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10104         }
10105         R_FrameData_ReturnToMark();
10106 }
10107
10108 float locboxvertex3f[6*4*3] =
10109 {
10110         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10111         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10112         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10113         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10114         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10115         1,0,0, 0,0,0, 0,1,0, 1,1,0
10116 };
10117
10118 unsigned short locboxelements[6*2*3] =
10119 {
10120          0, 1, 2, 0, 2, 3,
10121          4, 5, 6, 4, 6, 7,
10122          8, 9,10, 8,10,11,
10123         12,13,14, 12,14,15,
10124         16,17,18, 16,18,19,
10125         20,21,22, 20,22,23
10126 };
10127
10128 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10129 {
10130         int i, j;
10131         cl_locnode_t *loc = (cl_locnode_t *)ent;
10132         vec3_t mins, size;
10133         float vertex3f[6*4*3];
10134         CHECKGLERROR
10135         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10136         GL_DepthMask(false);
10137         GL_DepthRange(0, 1);
10138         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10139         GL_DepthTest(true);
10140         GL_CullFace(GL_NONE);
10141         R_EntityMatrix(&identitymatrix);
10142
10143 //      R_Mesh_ResetTextureState();
10144
10145         i = surfacelist[0];
10146         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10147                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10148                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10149                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10150
10151         if (VectorCompare(loc->mins, loc->maxs))
10152         {
10153                 VectorSet(size, 2, 2, 2);
10154                 VectorMA(loc->mins, -0.5f, size, mins);
10155         }
10156         else
10157         {
10158                 VectorCopy(loc->mins, mins);
10159                 VectorSubtract(loc->maxs, loc->mins, size);
10160         }
10161
10162         for (i = 0;i < 6*4*3;)
10163                 for (j = 0;j < 3;j++, i++)
10164                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10165
10166         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10167         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10168         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10169 }
10170
10171 void R_DrawLocs(void)
10172 {
10173         int index;
10174         cl_locnode_t *loc, *nearestloc;
10175         vec3_t center;
10176         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10177         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10178         {
10179                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10180                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10181         }
10182 }
10183
10184 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10185 {
10186         if (decalsystem->decals)
10187                 Mem_Free(decalsystem->decals);
10188         memset(decalsystem, 0, sizeof(*decalsystem));
10189 }
10190
10191 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)
10192 {
10193         tridecal_t *decal;
10194         tridecal_t *decals;
10195         int i;
10196
10197         // expand or initialize the system
10198         if (decalsystem->maxdecals <= decalsystem->numdecals)
10199         {
10200                 decalsystem_t old = *decalsystem;
10201                 qboolean useshortelements;
10202                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10203                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10204                 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)));
10205                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10206                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10207                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10208                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10209                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10210                 if (decalsystem->numdecals)
10211                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10212                 if (old.decals)
10213                         Mem_Free(old.decals);
10214                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10215                         decalsystem->element3i[i] = i;
10216                 if (useshortelements)
10217                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10218                                 decalsystem->element3s[i] = i;
10219         }
10220
10221         // grab a decal and search for another free slot for the next one
10222         decals = decalsystem->decals;
10223         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10224         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10225                 ;
10226         decalsystem->freedecal = i;
10227         if (decalsystem->numdecals <= i)
10228                 decalsystem->numdecals = i + 1;
10229
10230         // initialize the decal
10231         decal->lived = 0;
10232         decal->triangleindex = triangleindex;
10233         decal->surfaceindex = surfaceindex;
10234         decal->decalsequence = decalsequence;
10235         decal->color4f[0][0] = c0[0];
10236         decal->color4f[0][1] = c0[1];
10237         decal->color4f[0][2] = c0[2];
10238         decal->color4f[0][3] = 1;
10239         decal->color4f[1][0] = c1[0];
10240         decal->color4f[1][1] = c1[1];
10241         decal->color4f[1][2] = c1[2];
10242         decal->color4f[1][3] = 1;
10243         decal->color4f[2][0] = c2[0];
10244         decal->color4f[2][1] = c2[1];
10245         decal->color4f[2][2] = c2[2];
10246         decal->color4f[2][3] = 1;
10247         decal->vertex3f[0][0] = v0[0];
10248         decal->vertex3f[0][1] = v0[1];
10249         decal->vertex3f[0][2] = v0[2];
10250         decal->vertex3f[1][0] = v1[0];
10251         decal->vertex3f[1][1] = v1[1];
10252         decal->vertex3f[1][2] = v1[2];
10253         decal->vertex3f[2][0] = v2[0];
10254         decal->vertex3f[2][1] = v2[1];
10255         decal->vertex3f[2][2] = v2[2];
10256         decal->texcoord2f[0][0] = t0[0];
10257         decal->texcoord2f[0][1] = t0[1];
10258         decal->texcoord2f[1][0] = t1[0];
10259         decal->texcoord2f[1][1] = t1[1];
10260         decal->texcoord2f[2][0] = t2[0];
10261         decal->texcoord2f[2][1] = t2[1];
10262 }
10263
10264 extern cvar_t cl_decals_bias;
10265 extern cvar_t cl_decals_models;
10266 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10267 // baseparms, parms, temps
10268 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)
10269 {
10270         int cornerindex;
10271         int index;
10272         float v[9][3];
10273         const float *vertex3f;
10274         const float *normal3f;
10275         int numpoints;
10276         float points[2][9][3];
10277         float temp[3];
10278         float tc[9][2];
10279         float f;
10280         float c[9][4];
10281         const int *e;
10282
10283         e = rsurface.modelelement3i + 3*triangleindex;
10284
10285         vertex3f = rsurface.modelvertex3f;
10286         normal3f = rsurface.modelnormal3f;
10287
10288         if (normal3f)
10289         {
10290                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10291                 {
10292                         index = 3*e[cornerindex];
10293                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10294                 }
10295         }
10296         else
10297         {
10298                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10299                 {
10300                         index = 3*e[cornerindex];
10301                         VectorCopy(vertex3f + index, v[cornerindex]);
10302                 }
10303         }
10304
10305         // cull backfaces
10306         //TriangleNormal(v[0], v[1], v[2], normal);
10307         //if (DotProduct(normal, localnormal) < 0.0f)
10308         //      continue;
10309         // clip by each of the box planes formed from the projection matrix
10310         // if anything survives, we emit the decal
10311         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]);
10312         if (numpoints < 3)
10313                 return;
10314         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]);
10315         if (numpoints < 3)
10316                 return;
10317         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]);
10318         if (numpoints < 3)
10319                 return;
10320         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]);
10321         if (numpoints < 3)
10322                 return;
10323         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]);
10324         if (numpoints < 3)
10325                 return;
10326         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]);
10327         if (numpoints < 3)
10328                 return;
10329         // some part of the triangle survived, so we have to accept it...
10330         if (dynamic)
10331         {
10332                 // dynamic always uses the original triangle
10333                 numpoints = 3;
10334                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10335                 {
10336                         index = 3*e[cornerindex];
10337                         VectorCopy(vertex3f + index, v[cornerindex]);
10338                 }
10339         }
10340         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10341         {
10342                 // convert vertex positions to texcoords
10343                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10344                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10345                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10346                 // calculate distance fade from the projection origin
10347                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10348                 f = bound(0.0f, f, 1.0f);
10349                 c[cornerindex][0] = r * f;
10350                 c[cornerindex][1] = g * f;
10351                 c[cornerindex][2] = b * f;
10352                 c[cornerindex][3] = 1.0f;
10353                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10354         }
10355         if (dynamic)
10356                 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);
10357         else
10358                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10359                         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);
10360 }
10361 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)
10362 {
10363         matrix4x4_t projection;
10364         decalsystem_t *decalsystem;
10365         qboolean dynamic;
10366         dp_model_t *model;
10367         const msurface_t *surface;
10368         const msurface_t *surfaces;
10369         const int *surfacelist;
10370         const texture_t *texture;
10371         int numtriangles;
10372         int numsurfacelist;
10373         int surfacelistindex;
10374         int surfaceindex;
10375         int triangleindex;
10376         float localorigin[3];
10377         float localnormal[3];
10378         float localmins[3];
10379         float localmaxs[3];
10380         float localsize;
10381         //float normal[3];
10382         float planes[6][4];
10383         float angles[3];
10384         bih_t *bih;
10385         int bih_triangles_count;
10386         int bih_triangles[256];
10387         int bih_surfaces[256];
10388
10389         decalsystem = &ent->decalsystem;
10390         model = ent->model;
10391         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10392         {
10393                 R_DecalSystem_Reset(&ent->decalsystem);
10394                 return;
10395         }
10396
10397         if (!model->brush.data_leafs && !cl_decals_models.integer)
10398         {
10399                 if (decalsystem->model)
10400                         R_DecalSystem_Reset(decalsystem);
10401                 return;
10402         }
10403
10404         if (decalsystem->model != model)
10405                 R_DecalSystem_Reset(decalsystem);
10406         decalsystem->model = model;
10407
10408         RSurf_ActiveModelEntity(ent, true, false, false);
10409
10410         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10411         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10412         VectorNormalize(localnormal);
10413         localsize = worldsize*rsurface.inversematrixscale;
10414         localmins[0] = localorigin[0] - localsize;
10415         localmins[1] = localorigin[1] - localsize;
10416         localmins[2] = localorigin[2] - localsize;
10417         localmaxs[0] = localorigin[0] + localsize;
10418         localmaxs[1] = localorigin[1] + localsize;
10419         localmaxs[2] = localorigin[2] + localsize;
10420
10421         //VectorCopy(localnormal, planes[4]);
10422         //VectorVectors(planes[4], planes[2], planes[0]);
10423         AnglesFromVectors(angles, localnormal, NULL, false);
10424         AngleVectors(angles, planes[0], planes[2], planes[4]);
10425         VectorNegate(planes[0], planes[1]);
10426         VectorNegate(planes[2], planes[3]);
10427         VectorNegate(planes[4], planes[5]);
10428         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10429         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10430         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10431         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10432         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10433         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10434
10435 #if 1
10436 // works
10437 {
10438         matrix4x4_t forwardprojection;
10439         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10440         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10441 }
10442 #else
10443 // broken
10444 {
10445         float projectionvector[4][3];
10446         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10447         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10448         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10449         projectionvector[0][0] = planes[0][0] * ilocalsize;
10450         projectionvector[0][1] = planes[1][0] * ilocalsize;
10451         projectionvector[0][2] = planes[2][0] * ilocalsize;
10452         projectionvector[1][0] = planes[0][1] * ilocalsize;
10453         projectionvector[1][1] = planes[1][1] * ilocalsize;
10454         projectionvector[1][2] = planes[2][1] * ilocalsize;
10455         projectionvector[2][0] = planes[0][2] * ilocalsize;
10456         projectionvector[2][1] = planes[1][2] * ilocalsize;
10457         projectionvector[2][2] = planes[2][2] * ilocalsize;
10458         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10459         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10460         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10461         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10462 }
10463 #endif
10464
10465         dynamic = model->surfmesh.isanimated;
10466         numsurfacelist = model->nummodelsurfaces;
10467         surfacelist = model->sortedmodelsurfaces;
10468         surfaces = model->data_surfaces;
10469
10470         bih = NULL;
10471         bih_triangles_count = -1;
10472         if(!dynamic)
10473         {
10474                 if(model->render_bih.numleafs)
10475                         bih = &model->render_bih;
10476                 else if(model->collision_bih.numleafs)
10477                         bih = &model->collision_bih;
10478         }
10479         if(bih)
10480                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10481         if(bih_triangles_count == 0)
10482                 return;
10483         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10484                 return;
10485         if(bih_triangles_count > 0)
10486         {
10487                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10488                 {
10489                         surfaceindex = bih_surfaces[triangleindex];
10490                         surface = surfaces + surfaceindex;
10491                         texture = surface->texture;
10492                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10493                                 continue;
10494                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10495                                 continue;
10496                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10497                 }
10498         }
10499         else
10500         {
10501                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10502                 {
10503                         surfaceindex = surfacelist[surfacelistindex];
10504                         surface = surfaces + surfaceindex;
10505                         // check cull box first because it rejects more than any other check
10506                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10507                                 continue;
10508                         // skip transparent surfaces
10509                         texture = surface->texture;
10510                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10511                                 continue;
10512                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10513                                 continue;
10514                         numtriangles = surface->num_triangles;
10515                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10516                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10517                 }
10518         }
10519 }
10520
10521 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10522 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)
10523 {
10524         int renderentityindex;
10525         float worldmins[3];
10526         float worldmaxs[3];
10527         entity_render_t *ent;
10528
10529         if (!cl_decals_newsystem.integer)
10530                 return;
10531
10532         worldmins[0] = worldorigin[0] - worldsize;
10533         worldmins[1] = worldorigin[1] - worldsize;
10534         worldmins[2] = worldorigin[2] - worldsize;
10535         worldmaxs[0] = worldorigin[0] + worldsize;
10536         worldmaxs[1] = worldorigin[1] + worldsize;
10537         worldmaxs[2] = worldorigin[2] + worldsize;
10538
10539         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10540
10541         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10542         {
10543                 ent = r_refdef.scene.entities[renderentityindex];
10544                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10545                         continue;
10546
10547                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10548         }
10549 }
10550
10551 typedef struct r_decalsystem_splatqueue_s
10552 {
10553         vec3_t worldorigin;
10554         vec3_t worldnormal;
10555         float color[4];
10556         float tcrange[4];
10557         float worldsize;
10558         int decalsequence;
10559 }
10560 r_decalsystem_splatqueue_t;
10561
10562 int r_decalsystem_numqueued = 0;
10563 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10564
10565 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)
10566 {
10567         r_decalsystem_splatqueue_t *queue;
10568
10569         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10570                 return;
10571
10572         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10573         VectorCopy(worldorigin, queue->worldorigin);
10574         VectorCopy(worldnormal, queue->worldnormal);
10575         Vector4Set(queue->color, r, g, b, a);
10576         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10577         queue->worldsize = worldsize;
10578         queue->decalsequence = cl.decalsequence++;
10579 }
10580
10581 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10582 {
10583         int i;
10584         r_decalsystem_splatqueue_t *queue;
10585
10586         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10587                 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);
10588         r_decalsystem_numqueued = 0;
10589 }
10590
10591 extern cvar_t cl_decals_max;
10592 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10593 {
10594         int i;
10595         decalsystem_t *decalsystem = &ent->decalsystem;
10596         int numdecals;
10597         int killsequence;
10598         tridecal_t *decal;
10599         float frametime;
10600         float lifetime;
10601
10602         if (!decalsystem->numdecals)
10603                 return;
10604
10605         if (r_showsurfaces.integer)
10606                 return;
10607
10608         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10609         {
10610                 R_DecalSystem_Reset(decalsystem);
10611                 return;
10612         }
10613
10614         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10615         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10616
10617         if (decalsystem->lastupdatetime)
10618                 frametime = (cl.time - decalsystem->lastupdatetime);
10619         else
10620                 frametime = 0;
10621         decalsystem->lastupdatetime = cl.time;
10622         decal = decalsystem->decals;
10623         numdecals = decalsystem->numdecals;
10624
10625         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10626         {
10627                 if (decal->color4f[0][3])
10628                 {
10629                         decal->lived += frametime;
10630                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10631                         {
10632                                 memset(decal, 0, sizeof(*decal));
10633                                 if (decalsystem->freedecal > i)
10634                                         decalsystem->freedecal = i;
10635                         }
10636                 }
10637         }
10638         decal = decalsystem->decals;
10639         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10640                 numdecals--;
10641
10642         // collapse the array by shuffling the tail decals into the gaps
10643         for (;;)
10644         {
10645                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10646                         decalsystem->freedecal++;
10647                 if (decalsystem->freedecal == numdecals)
10648                         break;
10649                 decal[decalsystem->freedecal] = decal[--numdecals];
10650         }
10651
10652         decalsystem->numdecals = numdecals;
10653
10654         if (numdecals <= 0)
10655         {
10656                 // if there are no decals left, reset decalsystem
10657                 R_DecalSystem_Reset(decalsystem);
10658         }
10659 }
10660
10661 extern skinframe_t *decalskinframe;
10662 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10663 {
10664         int i;
10665         decalsystem_t *decalsystem = &ent->decalsystem;
10666         int numdecals;
10667         tridecal_t *decal;
10668         float faderate;
10669         float alpha;
10670         float *v3f;
10671         float *c4f;
10672         float *t2f;
10673         const int *e;
10674         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10675         int numtris = 0;
10676
10677         numdecals = decalsystem->numdecals;
10678         if (!numdecals)
10679                 return;
10680
10681         if (r_showsurfaces.integer)
10682                 return;
10683
10684         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10685         {
10686                 R_DecalSystem_Reset(decalsystem);
10687                 return;
10688         }
10689
10690         // if the model is static it doesn't matter what value we give for
10691         // wantnormals and wanttangents, so this logic uses only rules applicable
10692         // to a model, knowing that they are meaningless otherwise
10693         if (ent == r_refdef.scene.worldentity)
10694                 RSurf_ActiveWorldEntity();
10695         else
10696                 RSurf_ActiveModelEntity(ent, false, false, false);
10697
10698         decalsystem->lastupdatetime = cl.time;
10699         decal = decalsystem->decals;
10700
10701         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10702
10703         // update vertex positions for animated models
10704         v3f = decalsystem->vertex3f;
10705         c4f = decalsystem->color4f;
10706         t2f = decalsystem->texcoord2f;
10707         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10708         {
10709                 if (!decal->color4f[0][3])
10710                         continue;
10711
10712                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10713                         continue;
10714
10715                 // update color values for fading decals
10716                 if (decal->lived >= cl_decals_time.value)
10717                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10718                 else
10719                         alpha = 1.0f;
10720
10721                 c4f[ 0] = decal->color4f[0][0] * alpha;
10722                 c4f[ 1] = decal->color4f[0][1] * alpha;
10723                 c4f[ 2] = decal->color4f[0][2] * alpha;
10724                 c4f[ 3] = 1;
10725                 c4f[ 4] = decal->color4f[1][0] * alpha;
10726                 c4f[ 5] = decal->color4f[1][1] * alpha;
10727                 c4f[ 6] = decal->color4f[1][2] * alpha;
10728                 c4f[ 7] = 1;
10729                 c4f[ 8] = decal->color4f[2][0] * alpha;
10730                 c4f[ 9] = decal->color4f[2][1] * alpha;
10731                 c4f[10] = decal->color4f[2][2] * alpha;
10732                 c4f[11] = 1;
10733
10734                 t2f[0] = decal->texcoord2f[0][0];
10735                 t2f[1] = decal->texcoord2f[0][1];
10736                 t2f[2] = decal->texcoord2f[1][0];
10737                 t2f[3] = decal->texcoord2f[1][1];
10738                 t2f[4] = decal->texcoord2f[2][0];
10739                 t2f[5] = decal->texcoord2f[2][1];
10740
10741                 // update vertex positions for animated models
10742                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10743                 {
10744                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10745                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10746                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10747                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10748                 }
10749                 else
10750                 {
10751                         VectorCopy(decal->vertex3f[0], v3f);
10752                         VectorCopy(decal->vertex3f[1], v3f + 3);
10753                         VectorCopy(decal->vertex3f[2], v3f + 6);
10754                 }
10755
10756                 if (r_refdef.fogenabled)
10757                 {
10758                         alpha = RSurf_FogVertex(v3f);
10759                         VectorScale(c4f, alpha, c4f);
10760                         alpha = RSurf_FogVertex(v3f + 3);
10761                         VectorScale(c4f + 4, alpha, c4f + 4);
10762                         alpha = RSurf_FogVertex(v3f + 6);
10763                         VectorScale(c4f + 8, alpha, c4f + 8);
10764                 }
10765
10766                 v3f += 9;
10767                 c4f += 12;
10768                 t2f += 6;
10769                 numtris++;
10770         }
10771
10772         if (numtris > 0)
10773         {
10774                 r_refdef.stats.drawndecals += numtris;
10775
10776                 // now render the decals all at once
10777                 // (this assumes they all use one particle font texture!)
10778                 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);
10779 //              R_Mesh_ResetTextureState();
10780                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10781                 GL_DepthMask(false);
10782                 GL_DepthRange(0, 1);
10783                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10784                 GL_DepthTest(true);
10785                 GL_CullFace(GL_NONE);
10786                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10787                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10788                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10789         }
10790 }
10791
10792 static void R_DrawModelDecals(void)
10793 {
10794         int i, numdecals;
10795
10796         // fade faster when there are too many decals
10797         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10798         for (i = 0;i < r_refdef.scene.numentities;i++)
10799                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10800
10801         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10802         for (i = 0;i < r_refdef.scene.numentities;i++)
10803                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10804                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10805
10806         R_DecalSystem_ApplySplatEntitiesQueue();
10807
10808         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10809         for (i = 0;i < r_refdef.scene.numentities;i++)
10810                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10811
10812         r_refdef.stats.totaldecals += numdecals;
10813
10814         if (r_showsurfaces.integer)
10815                 return;
10816
10817         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10818
10819         for (i = 0;i < r_refdef.scene.numentities;i++)
10820         {
10821                 if (!r_refdef.viewcache.entityvisible[i])
10822                         continue;
10823                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10824                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10825         }
10826 }
10827
10828 extern cvar_t mod_collision_bih;
10829 void R_DrawDebugModel(void)
10830 {
10831         entity_render_t *ent = rsurface.entity;
10832         int i, j, k, l, flagsmask;
10833         const msurface_t *surface;
10834         dp_model_t *model = ent->model;
10835         vec3_t v;
10836
10837         switch(vid.renderpath)
10838         {
10839         case RENDERPATH_GL11:
10840         case RENDERPATH_GL13:
10841         case RENDERPATH_GL20:
10842                 break;
10843         case RENDERPATH_D3D9:
10844                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10845                 return;
10846         case RENDERPATH_D3D10:
10847                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10848                 return;
10849         case RENDERPATH_D3D11:
10850                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10851                 return;
10852         case RENDERPATH_SOFT:
10853                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10854                 return;
10855         case RENDERPATH_GLES2:
10856                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10857                 return;
10858         }
10859
10860         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10861
10862 //      R_Mesh_ResetTextureState();
10863         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10864         GL_DepthRange(0, 1);
10865         GL_DepthTest(!r_showdisabledepthtest.integer);
10866         GL_DepthMask(false);
10867         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10868
10869         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10870         {
10871                 int triangleindex;
10872                 int bihleafindex;
10873                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10874                 const q3mbrush_t *brush;
10875                 const bih_t *bih = &model->collision_bih;
10876                 const bih_leaf_t *bihleaf;
10877                 float vertex3f[3][3];
10878                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10879                 cullbox = false;
10880                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10881                 {
10882                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10883                                 continue;
10884                         switch (bihleaf->type)
10885                         {
10886                         case BIH_BRUSH:
10887                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10888                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10889                                 {
10890                                         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);
10891                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10892                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10893                                 }
10894                                 break;
10895                         case BIH_COLLISIONTRIANGLE:
10896                                 triangleindex = bihleaf->itemindex;
10897                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10898                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10899                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10900                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
10901                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10902                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10903                                 break;
10904                         case BIH_RENDERTRIANGLE:
10905                                 triangleindex = bihleaf->itemindex;
10906                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10907                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10908                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10909                                 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);
10910                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10911                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10912                                 break;
10913                         }
10914                 }
10915         }
10916
10917         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10918
10919         if (r_showtris.integer || (r_shownormals.value != 0))
10920         {
10921                 if (r_showdisabledepthtest.integer)
10922                 {
10923                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10924                         GL_DepthMask(false);
10925                 }
10926                 else
10927                 {
10928                         GL_BlendFunc(GL_ONE, GL_ZERO);
10929                         GL_DepthMask(true);
10930                 }
10931                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10932                 {
10933                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10934                                 continue;
10935                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10936                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10937                         {
10938                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10939                                 if (r_showtris.value > 0)
10940                                 {
10941                                         if (!rsurface.texture->currentlayers->depthmask)
10942                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10943                                         else if (ent == r_refdef.scene.worldentity)
10944                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10945                                         else
10946                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10947                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10948                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10949                                         RSurf_DrawBatch();
10950                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10951                                         CHECKGLERROR
10952                                 }
10953                                 if (r_shownormals.value < 0)
10954                                 {
10955                                         qglBegin(GL_LINES);
10956                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10957                                         {
10958                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10959                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10960                                                 qglVertex3f(v[0], v[1], v[2]);
10961                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10962                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10963                                                 qglVertex3f(v[0], v[1], v[2]);
10964                                         }
10965                                         qglEnd();
10966                                         CHECKGLERROR
10967                                 }
10968                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10969                                 {
10970                                         qglBegin(GL_LINES);
10971                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10972                                         {
10973                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10974                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10975                                                 qglVertex3f(v[0], v[1], v[2]);
10976                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10977                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10978                                                 qglVertex3f(v[0], v[1], v[2]);
10979                                         }
10980                                         qglEnd();
10981                                         CHECKGLERROR
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(0, r_refdef.view.colorscale, 0, 1);
10987                                                 qglVertex3f(v[0], v[1], v[2]);
10988                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + 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, 0, r_refdef.view.colorscale, 1);
10999                                                 qglVertex3f(v[0], v[1], v[2]);
11000                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + 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                                 }
11007                         }
11008                 }
11009                 rsurface.texture = NULL;
11010         }
11011 }
11012
11013 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11014 int r_maxsurfacelist = 0;
11015 const msurface_t **r_surfacelist = NULL;
11016 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11017 {
11018         int i, j, endj, flagsmask;
11019         dp_model_t *model = r_refdef.scene.worldmodel;
11020         msurface_t *surfaces;
11021         unsigned char *update;
11022         int numsurfacelist = 0;
11023         if (model == NULL)
11024                 return;
11025
11026         if (r_maxsurfacelist < model->num_surfaces)
11027         {
11028                 r_maxsurfacelist = model->num_surfaces;
11029                 if (r_surfacelist)
11030                         Mem_Free((msurface_t**)r_surfacelist);
11031                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11032         }
11033
11034         RSurf_ActiveWorldEntity();
11035
11036         surfaces = model->data_surfaces;
11037         update = model->brushq1.lightmapupdateflags;
11038
11039         // update light styles on this submodel
11040         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11041         {
11042                 model_brush_lightstyleinfo_t *style;
11043                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11044                 {
11045                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11046                         {
11047                                 int *list = style->surfacelist;
11048                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11049                                 for (j = 0;j < style->numsurfaces;j++)
11050                                         update[list[j]] = true;
11051                         }
11052                 }
11053         }
11054
11055         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11056
11057         if (debug)
11058         {
11059                 R_DrawDebugModel();
11060                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11061                 return;
11062         }
11063
11064         rsurface.lightmaptexture = NULL;
11065         rsurface.deluxemaptexture = NULL;
11066         rsurface.uselightmaptexture = false;
11067         rsurface.texture = NULL;
11068         rsurface.rtlight = NULL;
11069         numsurfacelist = 0;
11070         // add visible surfaces to draw list
11071         for (i = 0;i < model->nummodelsurfaces;i++)
11072         {
11073                 j = model->sortedmodelsurfaces[i];
11074                 if (r_refdef.viewcache.world_surfacevisible[j])
11075                         r_surfacelist[numsurfacelist++] = surfaces + j;
11076         }
11077         // update lightmaps if needed
11078         if (model->brushq1.firstrender)
11079         {
11080                 model->brushq1.firstrender = false;
11081                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11082                         if (update[j])
11083                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11084         }
11085         else if (update)
11086         {
11087                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11088                         if (r_refdef.viewcache.world_surfacevisible[j])
11089                                 if (update[j])
11090                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11091         }
11092         // don't do anything if there were no surfaces
11093         if (!numsurfacelist)
11094         {
11095                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11096                 return;
11097         }
11098         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11099
11100         // add to stats if desired
11101         if (r_speeds.integer && !skysurfaces && !depthonly)
11102         {
11103                 r_refdef.stats.world_surfaces += numsurfacelist;
11104                 for (j = 0;j < numsurfacelist;j++)
11105                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11106         }
11107
11108         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11109 }
11110
11111 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11112 {
11113         int i, j, endj, flagsmask;
11114         dp_model_t *model = ent->model;
11115         msurface_t *surfaces;
11116         unsigned char *update;
11117         int numsurfacelist = 0;
11118         if (model == NULL)
11119                 return;
11120
11121         if (r_maxsurfacelist < model->num_surfaces)
11122         {
11123                 r_maxsurfacelist = model->num_surfaces;
11124                 if (r_surfacelist)
11125                         Mem_Free((msurface_t **)r_surfacelist);
11126                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11127         }
11128
11129         // if the model is static it doesn't matter what value we give for
11130         // wantnormals and wanttangents, so this logic uses only rules applicable
11131         // to a model, knowing that they are meaningless otherwise
11132         if (ent == r_refdef.scene.worldentity)
11133                 RSurf_ActiveWorldEntity();
11134         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11135                 RSurf_ActiveModelEntity(ent, false, false, false);
11136         else if (prepass)
11137                 RSurf_ActiveModelEntity(ent, true, true, true);
11138         else if (depthonly)
11139         {
11140                 switch (vid.renderpath)
11141                 {
11142                 case RENDERPATH_GL20:
11143                 case RENDERPATH_D3D9:
11144                 case RENDERPATH_D3D10:
11145                 case RENDERPATH_D3D11:
11146                 case RENDERPATH_SOFT:
11147                 case RENDERPATH_GLES2:
11148                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11149                         break;
11150                 case RENDERPATH_GL13:
11151                 case RENDERPATH_GL11:
11152                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11153                         break;
11154                 }
11155         }
11156         else
11157         {
11158                 switch (vid.renderpath)
11159                 {
11160                 case RENDERPATH_GL20:
11161                 case RENDERPATH_D3D9:
11162                 case RENDERPATH_D3D10:
11163                 case RENDERPATH_D3D11:
11164                 case RENDERPATH_SOFT:
11165                 case RENDERPATH_GLES2:
11166                         RSurf_ActiveModelEntity(ent, true, true, false);
11167                         break;
11168                 case RENDERPATH_GL13:
11169                 case RENDERPATH_GL11:
11170                         RSurf_ActiveModelEntity(ent, true, false, false);
11171                         break;
11172                 }
11173         }
11174
11175         surfaces = model->data_surfaces;
11176         update = model->brushq1.lightmapupdateflags;
11177
11178         // update light styles
11179         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11180         {
11181                 model_brush_lightstyleinfo_t *style;
11182                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11183                 {
11184                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11185                         {
11186                                 int *list = style->surfacelist;
11187                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11188                                 for (j = 0;j < style->numsurfaces;j++)
11189                                         update[list[j]] = true;
11190                         }
11191                 }
11192         }
11193
11194         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11195
11196         if (debug)
11197         {
11198                 R_DrawDebugModel();
11199                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11200                 return;
11201         }
11202
11203         rsurface.lightmaptexture = NULL;
11204         rsurface.deluxemaptexture = NULL;
11205         rsurface.uselightmaptexture = false;
11206         rsurface.texture = NULL;
11207         rsurface.rtlight = NULL;
11208         numsurfacelist = 0;
11209         // add visible surfaces to draw list
11210         for (i = 0;i < model->nummodelsurfaces;i++)
11211                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11212         // don't do anything if there were no surfaces
11213         if (!numsurfacelist)
11214         {
11215                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11216                 return;
11217         }
11218         // update lightmaps if needed
11219         if (update)
11220         {
11221                 int updated = 0;
11222                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11223                 {
11224                         if (update[j])
11225                         {
11226                                 updated++;
11227                                 R_BuildLightMap(ent, surfaces + j);
11228                         }
11229                 }
11230         }
11231         if (update)
11232                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11233                         if (update[j])
11234                                 R_BuildLightMap(ent, surfaces + j);
11235         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11236
11237         // add to stats if desired
11238         if (r_speeds.integer && !skysurfaces && !depthonly)
11239         {
11240                 r_refdef.stats.entities_surfaces += numsurfacelist;
11241                 for (j = 0;j < numsurfacelist;j++)
11242                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11243         }
11244
11245         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11246 }
11247
11248 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11249 {
11250         static texture_t texture;
11251         static msurface_t surface;
11252         const msurface_t *surfacelist = &surface;
11253
11254         // fake enough texture and surface state to render this geometry
11255
11256         texture.update_lastrenderframe = -1; // regenerate this texture
11257         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11258         texture.currentskinframe = skinframe;
11259         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11260         texture.offsetmapping = OFFSETMAPPING_OFF;
11261         texture.offsetscale = 1;
11262         texture.specularscalemod = 1;
11263         texture.specularpowermod = 1;
11264
11265         surface.texture = &texture;
11266         surface.num_triangles = numtriangles;
11267         surface.num_firsttriangle = firsttriangle;
11268         surface.num_vertices = numvertices;
11269         surface.num_firstvertex = firstvertex;
11270
11271         // now render it
11272         rsurface.texture = R_GetCurrentTexture(surface.texture);
11273         rsurface.lightmaptexture = NULL;
11274         rsurface.deluxemaptexture = NULL;
11275         rsurface.uselightmaptexture = false;
11276         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11277 }
11278
11279 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)
11280 {
11281         static msurface_t surface;
11282         const msurface_t *surfacelist = &surface;
11283
11284         // fake enough texture and surface state to render this geometry
11285         surface.texture = texture;
11286         surface.num_triangles = numtriangles;
11287         surface.num_firsttriangle = firsttriangle;
11288         surface.num_vertices = numvertices;
11289         surface.num_firstvertex = firstvertex;
11290
11291         // now render it
11292         rsurface.texture = R_GetCurrentTexture(surface.texture);
11293         rsurface.lightmaptexture = NULL;
11294         rsurface.deluxemaptexture = NULL;
11295         rsurface.uselightmaptexture = false;
11296         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11297 }