]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Revert "properly use lseek64 on Linux for files larger than 2GB" because it breaks...
[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_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 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)"};
149 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)"};
150 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)"};
151 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)"};
152 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)"};
153 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)"};
154 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)"};
155 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)"};
156
157 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)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 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"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
163
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
168
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
176
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 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)"};
181 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
182 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
183 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
184 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
185 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
186 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
187
188 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"};
189
190 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"};
191
192 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
193
194 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
195 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"};
196 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
197 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
198 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
199 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
200 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)"};
201 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
202 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
203
204 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
205 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"};
206
207 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)"};
208
209 extern cvar_t v_glslgamma;
210
211 extern qboolean v_flipped_state;
212
213 static struct r_bloomstate_s
214 {
215         qboolean enabled;
216         qboolean hdr;
217
218         int bloomwidth, bloomheight;
219
220         int screentexturewidth, screentextureheight;
221         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
222
223         int bloomtexturewidth, bloomtextureheight;
224         rtexture_t *texture_bloom;
225
226         // arrays for rendering the screen passes
227         float screentexcoord2f[8];
228         float bloomtexcoord2f[8];
229         float offsettexcoord2f[8];
230
231         r_viewport_t viewport;
232 }
233 r_bloomstate;
234
235 r_waterstate_t r_waterstate;
236
237 /// shadow volume bsp struct with automatically growing nodes buffer
238 svbsp_t r_svbsp;
239
240 rtexture_t *r_texture_blanknormalmap;
241 rtexture_t *r_texture_white;
242 rtexture_t *r_texture_grey128;
243 rtexture_t *r_texture_black;
244 rtexture_t *r_texture_notexture;
245 rtexture_t *r_texture_whitecube;
246 rtexture_t *r_texture_normalizationcube;
247 rtexture_t *r_texture_fogattenuation;
248 rtexture_t *r_texture_fogheighttexture;
249 rtexture_t *r_texture_gammaramps;
250 unsigned int r_texture_gammaramps_serial;
251 //rtexture_t *r_texture_fogintensity;
252 rtexture_t *r_texture_reflectcube;
253
254 // TODO: hash lookups?
255 typedef struct cubemapinfo_s
256 {
257         char basename[64];
258         rtexture_t *texture;
259 }
260 cubemapinfo_t;
261
262 int r_texture_numcubemaps;
263 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
264
265 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
266 unsigned int r_numqueries;
267 unsigned int r_maxqueries;
268
269 typedef struct r_qwskincache_s
270 {
271         char name[MAX_QPATH];
272         skinframe_t *skinframe;
273 }
274 r_qwskincache_t;
275
276 static r_qwskincache_t *r_qwskincache;
277 static int r_qwskincache_size;
278
279 /// vertex coordinates for a quad that covers the screen exactly
280 extern const float r_screenvertex3f[12];
281 extern const float r_d3dscreenvertex3f[12];
282 const float r_screenvertex3f[12] =
283 {
284         0, 0, 0,
285         1, 0, 0,
286         1, 1, 0,
287         0, 1, 0
288 };
289 const float r_d3dscreenvertex3f[12] =
290 {
291         0, 1, 0,
292         1, 1, 0,
293         1, 0, 0,
294         0, 0, 0
295 };
296
297 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
298 {
299         int i;
300         for (i = 0;i < verts;i++)
301         {
302                 out[0] = in[0] * r;
303                 out[1] = in[1] * g;
304                 out[2] = in[2] * b;
305                 out[3] = in[3];
306                 in += 4;
307                 out += 4;
308         }
309 }
310
311 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
312 {
313         int i;
314         for (i = 0;i < verts;i++)
315         {
316                 out[0] = r;
317                 out[1] = g;
318                 out[2] = b;
319                 out[3] = a;
320                 out += 4;
321         }
322 }
323
324 // FIXME: move this to client?
325 void FOG_clear(void)
326 {
327         if (gamemode == GAME_NEHAHRA)
328         {
329                 Cvar_Set("gl_fogenable", "0");
330                 Cvar_Set("gl_fogdensity", "0.2");
331                 Cvar_Set("gl_fogred", "0.3");
332                 Cvar_Set("gl_foggreen", "0.3");
333                 Cvar_Set("gl_fogblue", "0.3");
334         }
335         r_refdef.fog_density = 0;
336         r_refdef.fog_red = 0;
337         r_refdef.fog_green = 0;
338         r_refdef.fog_blue = 0;
339         r_refdef.fog_alpha = 1;
340         r_refdef.fog_start = 0;
341         r_refdef.fog_end = 16384;
342         r_refdef.fog_height = 1<<30;
343         r_refdef.fog_fadedepth = 128;
344         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
345 }
346
347 static void R_BuildBlankTextures(void)
348 {
349         unsigned char data[4];
350         data[2] = 128; // normal X
351         data[1] = 128; // normal Y
352         data[0] = 255; // normal Z
353         data[3] = 128; // height
354         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
355         data[0] = 255;
356         data[1] = 255;
357         data[2] = 255;
358         data[3] = 255;
359         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
360         data[0] = 128;
361         data[1] = 128;
362         data[2] = 128;
363         data[3] = 255;
364         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 0;
366         data[1] = 0;
367         data[2] = 0;
368         data[3] = 255;
369         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370 }
371
372 static void R_BuildNoTexture(void)
373 {
374         int x, y;
375         unsigned char pix[16][16][4];
376         // this makes a light grey/dark grey checkerboard texture
377         for (y = 0;y < 16;y++)
378         {
379                 for (x = 0;x < 16;x++)
380                 {
381                         if ((y < 8) ^ (x < 8))
382                         {
383                                 pix[y][x][0] = 128;
384                                 pix[y][x][1] = 128;
385                                 pix[y][x][2] = 128;
386                                 pix[y][x][3] = 255;
387                         }
388                         else
389                         {
390                                 pix[y][x][0] = 64;
391                                 pix[y][x][1] = 64;
392                                 pix[y][x][2] = 64;
393                                 pix[y][x][3] = 255;
394                         }
395                 }
396         }
397         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
398 }
399
400 static void R_BuildWhiteCube(void)
401 {
402         unsigned char data[6*1*1*4];
403         memset(data, 255, sizeof(data));
404         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
405 }
406
407 static void R_BuildNormalizationCube(void)
408 {
409         int x, y, side;
410         vec3_t v;
411         vec_t s, t, intensity;
412 #define NORMSIZE 64
413         unsigned char *data;
414         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
415         for (side = 0;side < 6;side++)
416         {
417                 for (y = 0;y < NORMSIZE;y++)
418                 {
419                         for (x = 0;x < NORMSIZE;x++)
420                         {
421                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
422                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
423                                 switch(side)
424                                 {
425                                 default:
426                                 case 0:
427                                         v[0] = 1;
428                                         v[1] = -t;
429                                         v[2] = -s;
430                                         break;
431                                 case 1:
432                                         v[0] = -1;
433                                         v[1] = -t;
434                                         v[2] = s;
435                                         break;
436                                 case 2:
437                                         v[0] = s;
438                                         v[1] = 1;
439                                         v[2] = t;
440                                         break;
441                                 case 3:
442                                         v[0] = s;
443                                         v[1] = -1;
444                                         v[2] = -t;
445                                         break;
446                                 case 4:
447                                         v[0] = s;
448                                         v[1] = -t;
449                                         v[2] = 1;
450                                         break;
451                                 case 5:
452                                         v[0] = -s;
453                                         v[1] = -t;
454                                         v[2] = -1;
455                                         break;
456                                 }
457                                 intensity = 127.0f / sqrt(DotProduct(v, v));
458                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
459                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
460                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
461                                 data[((side*64+y)*64+x)*4+3] = 255;
462                         }
463                 }
464         }
465         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
466         Mem_Free(data);
467 }
468
469 static void R_BuildFogTexture(void)
470 {
471         int x, b;
472 #define FOGWIDTH 256
473         unsigned char data1[FOGWIDTH][4];
474         //unsigned char data2[FOGWIDTH][4];
475         double d, r, alpha;
476
477         r_refdef.fogmasktable_start = r_refdef.fog_start;
478         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
479         r_refdef.fogmasktable_range = r_refdef.fogrange;
480         r_refdef.fogmasktable_density = r_refdef.fog_density;
481
482         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
483         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
484         {
485                 d = (x * r - r_refdef.fogmasktable_start);
486                 if(developer_extra.integer)
487                         Con_DPrintf("%f ", d);
488                 d = max(0, d);
489                 if (r_fog_exp2.integer)
490                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
491                 else
492                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
493                 if(developer_extra.integer)
494                         Con_DPrintf(" : %f ", alpha);
495                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
496                 if(developer_extra.integer)
497                         Con_DPrintf(" = %f\n", alpha);
498                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
499         }
500
501         for (x = 0;x < FOGWIDTH;x++)
502         {
503                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
504                 data1[x][0] = b;
505                 data1[x][1] = b;
506                 data1[x][2] = b;
507                 data1[x][3] = 255;
508                 //data2[x][0] = 255 - b;
509                 //data2[x][1] = 255 - b;
510                 //data2[x][2] = 255 - b;
511                 //data2[x][3] = 255;
512         }
513         if (r_texture_fogattenuation)
514         {
515                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
516                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
517         }
518         else
519         {
520                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
521                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
522         }
523 }
524
525 static void R_BuildFogHeightTexture(void)
526 {
527         unsigned char *inpixels;
528         int size;
529         int x;
530         int y;
531         int j;
532         float c[4];
533         float f;
534         inpixels = NULL;
535         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
536         if (r_refdef.fogheighttexturename[0])
537                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
538         if (!inpixels)
539         {
540                 r_refdef.fog_height_tablesize = 0;
541                 if (r_texture_fogheighttexture)
542                         R_FreeTexture(r_texture_fogheighttexture);
543                 r_texture_fogheighttexture = NULL;
544                 if (r_refdef.fog_height_table2d)
545                         Mem_Free(r_refdef.fog_height_table2d);
546                 r_refdef.fog_height_table2d = NULL;
547                 if (r_refdef.fog_height_table1d)
548                         Mem_Free(r_refdef.fog_height_table1d);
549                 r_refdef.fog_height_table1d = NULL;
550                 return;
551         }
552         size = image_width;
553         r_refdef.fog_height_tablesize = size;
554         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
555         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
556         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
557         Mem_Free(inpixels);
558         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
559         // average fog color table accounting for every fog layer between a point
560         // and the camera.  (Note: attenuation is handled separately!)
561         for (y = 0;y < size;y++)
562         {
563                 for (x = 0;x < size;x++)
564                 {
565                         Vector4Clear(c);
566                         f = 0;
567                         if (x < y)
568                         {
569                                 for (j = x;j <= y;j++)
570                                 {
571                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
572                                         f++;
573                                 }
574                         }
575                         else
576                         {
577                                 for (j = x;j >= y;j--)
578                                 {
579                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
580                                         f++;
581                                 }
582                         }
583                         f = 1.0f / f;
584                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
585                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
586                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
587                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
588                 }
589         }
590         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
591 }
592
593 //=======================================================================================================================================================
594
595 static const char *builtinshaderstring =
596 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
597 "// written by Forest 'LordHavoc' Hale\n"
598 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
599 "\n"
600 "// GL ES shaders use precision modifiers, standard GL does not\n"
601 "#ifndef GL_ES\n"
602 "#define lowp\n"
603 "#define mediump\n"
604 "#define highp\n"
605 "#endif\n"
606 "\n"
607 "#ifdef VERTEX_SHADER\n"
608 "attribute vec4 Attrib_Position;  // vertex\n"
609 "attribute vec4 Attrib_Color;     // color\n"
610 "attribute vec4 Attrib_TexCoord0; // material texcoords\n"
611 "attribute vec3 Attrib_TexCoord1; // svector\n"
612 "attribute vec3 Attrib_TexCoord2; // tvector\n"
613 "attribute vec3 Attrib_TexCoord3; // normal\n"
614 "attribute vec4 Attrib_TexCoord4; // lightmap texcoords\n"
615 "#endif\n"
616 "varying lowp vec4 VertexColor;\n"
617 "\n"
618 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
619 "# define USEFOG\n"
620 "#endif\n"
621 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
622 "#define USELIGHTMAP\n"
623 "#endif\n"
624 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
625 "#define USEEYEVECTOR\n"
626 "#endif\n"
627 "\n"
628 "#ifdef USESHADOWMAP2D\n"
629 "# ifdef GL_EXT_gpu_shader4\n"
630 "#   extension GL_EXT_gpu_shader4 : enable\n"
631 "# endif\n"
632 "# ifdef GL_ARB_texture_gather\n"
633 "#   extension GL_ARB_texture_gather : enable\n"
634 "# else\n"
635 "#   ifdef GL_AMD_texture_texture4\n"
636 "#     extension GL_AMD_texture_texture4 : enable\n"
637 "#   endif\n"
638 "# endif\n"
639 "#endif\n"
640 "\n"
641 "//#ifdef USESHADOWSAMPLER\n"
642 "//# extension GL_ARB_shadow : enable\n"
643 "//#endif\n"
644 "\n"
645 "//#ifdef __GLSL_CG_DATA_TYPES\n"
646 "//# define myhalf half\n"
647 "//# define myhalf2 half2\n"
648 "//# define myhalf3 half3\n"
649 "//# define myhalf4 half4\n"
650 "//#else\n"
651 "# define myhalf mediump float\n"
652 "# define myhalf2 mediump vec2\n"
653 "# define myhalf3 mediump vec3\n"
654 "# define myhalf4 mediump vec4\n"
655 "//#endif\n"
656 "\n"
657 "#ifdef VERTEX_SHADER\n"
658 "uniform highp mat4 ModelViewProjectionMatrix;\n"
659 "#endif\n"
660 "\n"
661 "#ifdef MODE_DEPTH_OR_SHADOW\n"
662 "#ifdef VERTEX_SHADER\n"
663 "void main(void)\n"
664 "{\n"
665 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
666 "}\n"
667 "#endif\n"
668 "#else // !MODE_DEPTH_ORSHADOW\n"
669 "\n"
670 "\n"
671 "\n"
672 "\n"
673 "#ifdef MODE_SHOWDEPTH\n"
674 "#ifdef VERTEX_SHADER\n"
675 "void main(void)\n"
676 "{\n"
677 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
678 "       VertexColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
679 "}\n"
680 "#endif\n"
681 "\n"
682 "#ifdef FRAGMENT_SHADER\n"
683 "void main(void)\n"
684 "{\n"
685 "       gl_FragColor = VertexColor;\n"
686 "}\n"
687 "#endif\n"
688 "#else // !MODE_SHOWDEPTH\n"
689 "\n"
690 "\n"
691 "\n"
692 "\n"
693 "#ifdef MODE_POSTPROCESS\n"
694 "varying mediump vec2 TexCoord1;\n"
695 "varying mediump vec2 TexCoord2;\n"
696 "\n"
697 "#ifdef VERTEX_SHADER\n"
698 "void main(void)\n"
699 "{\n"
700 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
701 "       TexCoord1 = Attrib_TexCoord0.xy;\n"
702 "#ifdef USEBLOOM\n"
703 "       TexCoord2 = Attrib_TexCoord4.xy;\n"
704 "#endif\n"
705 "}\n"
706 "#endif\n"
707 "\n"
708 "#ifdef FRAGMENT_SHADER\n"
709 "uniform sampler2D Texture_First;\n"
710 "#ifdef USEBLOOM\n"
711 "uniform sampler2D Texture_Second;\n"
712 "uniform lowp vec4 BloomColorSubtract;\n"
713 "#endif\n"
714 "#ifdef USEGAMMARAMPS\n"
715 "uniform sampler2D Texture_GammaRamps;\n"
716 "#endif\n"
717 "#ifdef USESATURATION\n"
718 "uniform lowp float Saturation;\n"
719 "#endif\n"
720 "#ifdef USEVIEWTINT\n"
721 "uniform lowp vec4 ViewTintColor;\n"
722 "#endif\n"
723 "//uncomment these if you want to use them:\n"
724 "uniform mediump vec4 UserVec1;\n"
725 "uniform mediump vec4 UserVec2;\n"
726 "// uniform mediump vec4 UserVec3;\n"
727 "// uniform mediump vec4 UserVec4;\n"
728 "// uniform highp float ClientTime;\n"
729 "uniform mediump vec2 PixelSize;\n"
730 "void main(void)\n"
731 "{\n"
732 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
733 "#ifdef USEBLOOM\n"
734 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
735 "#endif\n"
736 "#ifdef USEVIEWTINT\n"
737 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
738 "#endif\n"
739 "\n"
740 "#ifdef USEPOSTPROCESSING\n"
741 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
742 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
743 "       float sobel = 1.0;\n"
744 "       // vec2 ts = textureSize(Texture_First, 0);\n"
745 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
746 "       vec2 px = PixelSize;\n"
747 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
748 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
749 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
750 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
751 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
752 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
753 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
754 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
755 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
756 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
757 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
758 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
759 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
760 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
761 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
762 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
763 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
764 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
765 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
766 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
767 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
768 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
769 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
770 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
771 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
772 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
773 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
774 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
775 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
776 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
777 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
778 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
779 "#endif\n"
780 "\n"
781 "#ifdef USESATURATION\n"
782 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
783 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
784 "       // 'vampire sight' effect, wheres red is compensated\n"
785 "       #ifdef SATURATION_REDCOMPENSATE\n"
786 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
787 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
788 "               gl_FragColor.r += rboost;\n"
789 "       #else\n"
790 "               // normal desaturation\n"
791 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
792 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
793 "       #endif\n"
794 "#endif\n"
795 "\n"
796 "#ifdef USEGAMMARAMPS\n"
797 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
798 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
799 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
800 "#endif\n"
801 "}\n"
802 "#endif\n"
803 "#else // !MODE_POSTPROCESS\n"
804 "\n"
805 "\n"
806 "\n"
807 "\n"
808 "#ifdef MODE_GENERIC\n"
809 "#ifdef USEDIFFUSE\n"
810 "varying mediump vec2 TexCoord1;\n"
811 "#endif\n"
812 "#ifdef USESPECULAR\n"
813 "varying mediump vec2 TexCoord2;\n"
814 "#endif\n"
815 "#ifdef VERTEX_SHADER\n"
816 "void main(void)\n"
817 "{\n"
818 "       VertexColor = Attrib_Color;\n"
819 "#ifdef USEDIFFUSE\n"
820 "       TexCoord1 = Attrib_TexCoord0.xy;\n"
821 "#endif\n"
822 "#ifdef USESPECULAR\n"
823 "       TexCoord2 = Attrib_TexCoord1.xy;\n"
824 "#endif\n"
825 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
826 "}\n"
827 "#endif\n"
828 "\n"
829 "#ifdef FRAGMENT_SHADER\n"
830 "#ifdef USEDIFFUSE\n"
831 "uniform sampler2D Texture_First;\n"
832 "#endif\n"
833 "#ifdef USESPECULAR\n"
834 "uniform sampler2D Texture_Second;\n"
835 "#endif\n"
836 "\n"
837 "void main(void)\n"
838 "{\n"
839 "#ifdef USEVIEWTINT\n"
840 "       gl_FragColor = VertexColor;\n"
841 "#else\n"
842 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
843 "#endif\n"
844 "#ifdef USEDIFFUSE\n"
845 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
846 "#endif\n"
847 "\n"
848 "#ifdef USESPECULAR\n"
849 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
850 "# ifdef USECOLORMAPPING\n"
851 "       gl_FragColor *= tex2;\n"
852 "# endif\n"
853 "# ifdef USEGLOW\n"
854 "       gl_FragColor += tex2;\n"
855 "# endif\n"
856 "# ifdef USEVERTEXTEXTUREBLEND\n"
857 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
858 "# endif\n"
859 "#endif\n"
860 "}\n"
861 "#endif\n"
862 "#else // !MODE_GENERIC\n"
863 "\n"
864 "\n"
865 "\n"
866 "\n"
867 "#ifdef MODE_BLOOMBLUR\n"
868 "varying mediump vec2 TexCoord;\n"
869 "#ifdef VERTEX_SHADER\n"
870 "void main(void)\n"
871 "{\n"
872 "       VertexColor = Attrib_Color;\n"
873 "       TexCoord = Attrib_TexCoord0.xy;\n"
874 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
875 "}\n"
876 "#endif\n"
877 "\n"
878 "#ifdef FRAGMENT_SHADER\n"
879 "uniform sampler2D Texture_First;\n"
880 "uniform mediump vec4 BloomBlur_Parameters;\n"
881 "\n"
882 "void main(void)\n"
883 "{\n"
884 "       int i;\n"
885 "       vec2 tc = TexCoord;\n"
886 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
887 "       tc += BloomBlur_Parameters.xy;\n"
888 "       for (i = 1;i < SAMPLES;i++)\n"
889 "       {\n"
890 "               color += texture2D(Texture_First, tc).rgb;\n"
891 "               tc += BloomBlur_Parameters.xy;\n"
892 "       }\n"
893 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
894 "}\n"
895 "#endif\n"
896 "#else // !MODE_BLOOMBLUR\n"
897 "#ifdef MODE_REFRACTION\n"
898 "varying mediump vec2 TexCoord;\n"
899 "varying highp vec4 ModelViewProjectionPosition;\n"
900 "uniform highp mat4 TexMatrix;\n"
901 "#ifdef VERTEX_SHADER\n"
902 "\n"
903 "void main(void)\n"
904 "{\n"
905 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
906 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
907 "       ModelViewProjectionPosition = gl_Position;\n"
908 "}\n"
909 "#endif\n"
910 "\n"
911 "#ifdef FRAGMENT_SHADER\n"
912 "uniform sampler2D Texture_Normal;\n"
913 "uniform sampler2D Texture_Refraction;\n"
914 "uniform sampler2D Texture_Reflection;\n"
915 "\n"
916 "uniform mediump vec4 DistortScaleRefractReflect;\n"
917 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
918 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
919 "uniform lowp vec4 RefractColor;\n"
920 "uniform lowp vec4 ReflectColor;\n"
921 "uniform mediump float ReflectFactor;\n"
922 "uniform mediump float ReflectOffset;\n"
923 "\n"
924 "void main(void)\n"
925 "{\n"
926 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
927 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
928 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
929 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
930 "       // FIXME temporary hack to detect the case that the reflection\n"
931 "       // gets blackened at edges due to leaving the area that contains actual\n"
932 "       // content.\n"
933 "       // Remove this 'ack once we have a better way to stop this thing from\n"
934 "       // 'appening.\n"
935 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
936 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
937 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
938 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
939 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
940 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
941 "}\n"
942 "#endif\n"
943 "#else // !MODE_REFRACTION\n"
944 "\n"
945 "\n"
946 "\n"
947 "\n"
948 "#ifdef MODE_WATER\n"
949 "varying mediump vec2 TexCoord;\n"
950 "varying highp vec3 EyeVector;\n"
951 "varying highp vec4 ModelViewProjectionPosition;\n"
952 "#ifdef VERTEX_SHADER\n"
953 "uniform highp vec3 EyePosition;\n"
954 "uniform highp mat4 TexMatrix;\n"
955 "\n"
956 "void main(void)\n"
957 "{\n"
958 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
959 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
960 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
961 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
962 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
963 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
964 "       ModelViewProjectionPosition = gl_Position;\n"
965 "}\n"
966 "#endif\n"
967 "\n"
968 "#ifdef FRAGMENT_SHADER\n"
969 "uniform sampler2D Texture_Normal;\n"
970 "uniform sampler2D Texture_Refraction;\n"
971 "uniform sampler2D Texture_Reflection;\n"
972 "\n"
973 "uniform mediump vec4 DistortScaleRefractReflect;\n"
974 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
975 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
976 "uniform lowp vec4 RefractColor;\n"
977 "uniform lowp vec4 ReflectColor;\n"
978 "uniform mediump float ReflectFactor;\n"
979 "uniform mediump float ReflectOffset;\n"
980 "uniform highp float ClientTime;\n"
981 "#ifdef USENORMALMAPSCROLLBLEND\n"
982 "uniform highp vec2 NormalmapScrollBlend;\n"
983 "#endif\n"
984 "\n"
985 "void main(void)\n"
986 "{\n"
987 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
988 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
989 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
990 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
991 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
992 "       #ifdef USENORMALMAPSCROLLBLEND\n"
993 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
994 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
995 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
996 "       #else\n"
997 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
998 "       #endif\n"
999 "       // FIXME temporary hack to detect the case that the reflection\n"
1000 "       // gets blackened at edges due to leaving the area that contains actual\n"
1001 "       // content.\n"
1002 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1003 "       // 'appening.\n"
1004 "       float f  = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
1005 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
1006 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
1007 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
1008 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1009 "       f  = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
1010 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
1011 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
1012 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
1013 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1014 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1015 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
1016 "}\n"
1017 "#endif\n"
1018 "#else // !MODE_WATER\n"
1019 "\n"
1020 "\n"
1021 "\n"
1022 "\n"
1023 "// common definitions between vertex shader and fragment shader:\n"
1024 "\n"
1025 "varying mediump vec2 TexCoord;\n"
1026 "#ifdef USEVERTEXTEXTUREBLEND\n"
1027 "varying mediump vec2 TexCoord2;\n"
1028 "#endif\n"
1029 "#ifdef USELIGHTMAP\n"
1030 "varying mediump vec2 TexCoordLightmap;\n"
1031 "#endif\n"
1032 "\n"
1033 "#ifdef MODE_LIGHTSOURCE\n"
1034 "varying mediump vec3 CubeVector;\n"
1035 "#endif\n"
1036 "\n"
1037 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1038 "varying mediump vec3 LightVector;\n"
1039 "#endif\n"
1040 "\n"
1041 "#ifdef USEEYEVECTOR\n"
1042 "varying highp vec3 EyeVector;\n"
1043 "#endif\n"
1044 "#ifdef USEFOG\n"
1045 "varying highp vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1046 "#endif\n"
1047 "\n"
1048 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1049 "varying lowp vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1050 "varying lowp vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1051 "varying lowp vec3 VectorR; // direction of R texcoord (surface normal)\n"
1052 "#endif\n"
1053 "\n"
1054 "#ifdef USEREFLECTION\n"
1055 "varying highp vec4 ModelViewProjectionPosition;\n"
1056 "#endif\n"
1057 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1058 "uniform highp vec3 LightPosition;\n"
1059 "varying highp vec4 ModelViewPosition;\n"
1060 "#endif\n"
1061 "\n"
1062 "#ifdef MODE_LIGHTSOURCE\n"
1063 "uniform highp vec3 LightPosition;\n"
1064 "#endif\n"
1065 "uniform highp vec3 EyePosition;\n"
1066 "#ifdef MODE_LIGHTDIRECTION\n"
1067 "uniform highp vec3 LightDir;\n"
1068 "#endif\n"
1069 "uniform highp vec4 FogPlane;\n"
1070 "\n"
1071 "#ifdef USESHADOWMAPORTHO\n"
1072 "varying mediump vec3 ShadowMapTC;\n"
1073 "#endif\n"
1074 "\n"
1075 "#ifdef USEBOUNCEGRID\n"
1076 "varying mediump vec3 BounceGridTexCoord;\n"
1077 "#endif\n"
1078 "\n"
1079 "\n"
1080 "\n"
1081 "\n"
1082 "\n"
1083 "\n"
1084 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1085 "\n"
1086 "// fragment shader specific:\n"
1087 "#ifdef FRAGMENT_SHADER\n"
1088 "\n"
1089 "uniform sampler2D Texture_Normal;\n"
1090 "uniform sampler2D Texture_Color;\n"
1091 "uniform sampler2D Texture_Gloss;\n"
1092 "#ifdef USEGLOW\n"
1093 "uniform sampler2D Texture_Glow;\n"
1094 "#endif\n"
1095 "#ifdef USEVERTEXTEXTUREBLEND\n"
1096 "uniform sampler2D Texture_SecondaryNormal;\n"
1097 "uniform sampler2D Texture_SecondaryColor;\n"
1098 "uniform sampler2D Texture_SecondaryGloss;\n"
1099 "#ifdef USEGLOW\n"
1100 "uniform sampler2D Texture_SecondaryGlow;\n"
1101 "#endif\n"
1102 "#endif\n"
1103 "#ifdef USECOLORMAPPING\n"
1104 "uniform sampler2D Texture_Pants;\n"
1105 "uniform sampler2D Texture_Shirt;\n"
1106 "#endif\n"
1107 "#ifdef USEFOG\n"
1108 "#ifdef USEFOGHEIGHTTEXTURE\n"
1109 "uniform sampler2D Texture_FogHeightTexture;\n"
1110 "#endif\n"
1111 "uniform sampler2D Texture_FogMask;\n"
1112 "#endif\n"
1113 "#ifdef USELIGHTMAP\n"
1114 "uniform sampler2D Texture_Lightmap;\n"
1115 "#endif\n"
1116 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1117 "uniform sampler2D Texture_Deluxemap;\n"
1118 "#endif\n"
1119 "#ifdef USEREFLECTION\n"
1120 "uniform sampler2D Texture_Reflection;\n"
1121 "#endif\n"
1122 "\n"
1123 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1124 "uniform sampler2D Texture_ScreenDepth;\n"
1125 "uniform sampler2D Texture_ScreenNormalMap;\n"
1126 "#endif\n"
1127 "#ifdef USEDEFERREDLIGHTMAP\n"
1128 "uniform sampler2D Texture_ScreenDiffuse;\n"
1129 "uniform sampler2D Texture_ScreenSpecular;\n"
1130 "#endif\n"
1131 "\n"
1132 "uniform lowp vec3 Color_Pants;\n"
1133 "uniform lowp vec3 Color_Shirt;\n"
1134 "uniform lowp vec3 FogColor;\n"
1135 "\n"
1136 "#ifdef USEFOG\n"
1137 "uniform highp float FogRangeRecip;\n"
1138 "uniform highp float FogPlaneViewDist;\n"
1139 "uniform highp float FogHeightFade;\n"
1140 "vec3 FogVertex(vec3 surfacecolor)\n"
1141 "{\n"
1142 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1143 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1144 "       float fogfrac;\n"
1145 "#ifdef USEFOGHEIGHTTEXTURE\n"
1146 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1147 "       fogfrac = fogheightpixel.a;\n"
1148 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1149 "#else\n"
1150 "# ifdef USEFOGOUTSIDE\n"
1151 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1152 "# else\n"
1153 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1154 "# endif\n"
1155 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1156 "#endif\n"
1157 "}\n"
1158 "#endif\n"
1159 "\n"
1160 "#ifdef USEOFFSETMAPPING\n"
1161 "uniform mediump float OffsetMapping_Scale;\n"
1162 "vec2 OffsetMapping(vec2 TexCoord)\n"
1163 "{\n"
1164 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1165 "       // 14 sample relief mapping: linear search and then binary search\n"
1166 "       // this basically steps forward a small amount repeatedly until it finds\n"
1167 "       // itself inside solid, then jitters forward and back using decreasing\n"
1168 "       // amounts to find the impact\n"
1169 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1170 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1171 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1172 "       vec3 RT = vec3(TexCoord, 1);\n"
1173 "       OffsetVector *= 0.1;\n"
1174 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1175 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1176 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1177 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1178 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1179 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1180 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1181 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1182 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1183 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1184 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1185 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1186 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1187 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1188 "       return RT.xy;\n"
1189 "#else\n"
1190 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1191 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1192 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1193 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1194 "       OffsetVector *= 0.5;\n"
1195 "       TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
1196 "       TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
1197 "       return TexCoord;\n"
1198 "#endif\n"
1199 "}\n"
1200 "#endif // USEOFFSETMAPPING\n"
1201 "\n"
1202 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1203 "uniform sampler2D Texture_Attenuation;\n"
1204 "uniform samplerCube Texture_Cube;\n"
1205 "#endif\n"
1206 "\n"
1207 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1208 "\n"
1209 "#ifdef USESHADOWMAP2D\n"
1210 "# ifdef USESHADOWSAMPLER\n"
1211 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1212 "# else\n"
1213 "uniform sampler2D Texture_ShadowMap2D;\n"
1214 "# endif\n"
1215 "#endif\n"
1216 "\n"
1217 "#ifdef USESHADOWMAPVSDCT\n"
1218 "uniform samplerCube Texture_CubeProjection;\n"
1219 "#endif\n"
1220 "\n"
1221 "#if defined(USESHADOWMAP2D)\n"
1222 "uniform mediump vec2 ShadowMap_TextureScale;\n"
1223 "uniform mediump vec4 ShadowMap_Parameters;\n"
1224 "#endif\n"
1225 "\n"
1226 "#if defined(USESHADOWMAP2D)\n"
1227 "# ifdef USESHADOWMAPORTHO\n"
1228 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1229 "# else\n"
1230 "#  ifdef USESHADOWMAPVSDCT\n"
1231 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1232 "{\n"
1233 "       vec3 adir = abs(dir);\n"
1234 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1235 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1236 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1237 "}\n"
1238 "#  else\n"
1239 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1240 "{\n"
1241 "       vec3 adir = abs(dir);\n"
1242 "       float ma = adir.z;\n"
1243 "       vec4 proj = vec4(dir, 2.5);\n"
1244 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1245 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1246 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1247 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1248 "}\n"
1249 "#  endif\n"
1250 "# endif\n"
1251 "#endif // defined(USESHADOWMAP2D)\n"
1252 "\n"
1253 "# ifdef USESHADOWMAP2D\n"
1254 "float ShadowMapCompare(vec3 dir)\n"
1255 "{\n"
1256 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1257 "       float f;\n"
1258 "\n"
1259 "#  ifdef USESHADOWSAMPLER\n"
1260 "#    ifdef USESHADOWMAPPCF\n"
1261 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1262 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1263 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1264 "#    else\n"
1265 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1266 "#    endif\n"
1267 "#  else\n"
1268 "#    ifdef USESHADOWMAPPCF\n"
1269 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1270 "#      ifdef GL_ARB_texture_gather\n"
1271 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1272 "#      else\n"
1273 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1274 "#      endif\n"
1275 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1276 "#      if USESHADOWMAPPCF > 1\n"
1277 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1278 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1279 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1280 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1281 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1282 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1283 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1284 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1285 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1286 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1287 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1288 "       locols.yz += group2.ab;\n"
1289 "       hicols.yz += group8.rg;\n"
1290 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1291 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1292 "                               mix(locols, hicols, offset.y);\n"
1293 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1294 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1295 "       f = dot(cols, vec4(1.0/25.0));\n"
1296 "#      else\n"
1297 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1298 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1299 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1300 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1301 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1302 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1303 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1304 "#      endif\n"
1305 "#     else\n"
1306 "#      ifdef GL_EXT_gpu_shader4\n"
1307 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1308 "#      else\n"
1309 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1310 "#      endif\n"
1311 "#      if USESHADOWMAPPCF > 1\n"
1312 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1313 "       center *= ShadowMap_TextureScale;\n"
1314 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1315 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1316 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1317 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1318 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1319 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1320 "#      else\n"
1321 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1322 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1323 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1324 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1325 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1326 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1327 "#      endif\n"
1328 "#     endif\n"
1329 "#    else\n"
1330 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1331 "#    endif\n"
1332 "#  endif\n"
1333 "#  ifdef USESHADOWMAPORTHO\n"
1334 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1335 "#  else\n"
1336 "       return f;\n"
1337 "#  endif\n"
1338 "}\n"
1339 "# endif\n"
1340 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1341 "#endif // FRAGMENT_SHADER\n"
1342 "\n"
1343 "\n"
1344 "\n"
1345 "\n"
1346 "#ifdef MODE_DEFERREDGEOMETRY\n"
1347 "#ifdef VERTEX_SHADER\n"
1348 "uniform highp mat4 TexMatrix;\n"
1349 "#ifdef USEVERTEXTEXTUREBLEND\n"
1350 "uniform highp mat4 BackgroundTexMatrix;\n"
1351 "#endif\n"
1352 "uniform highp mat4 ModelViewMatrix;\n"
1353 "void main(void)\n"
1354 "{\n"
1355 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1356 "#ifdef USEVERTEXTEXTUREBLEND\n"
1357 "       VertexColor = Attrib_Color;\n"
1358 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1359 "#endif\n"
1360 "\n"
1361 "       // transform unnormalized eye direction into tangent space\n"
1362 "#ifdef USEOFFSETMAPPING\n"
1363 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1364 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1365 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1366 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1367 "#endif\n"
1368 "\n"
1369 "       VectorS = (ModelViewMatrix * vec4(Attrib_TexCoord1.xyz, 0)).xyz;\n"
1370 "       VectorT = (ModelViewMatrix * vec4(Attrib_TexCoord2.xyz, 0)).xyz;\n"
1371 "       VectorR = (ModelViewMatrix * vec4(Attrib_TexCoord3.xyz, 0)).xyz;\n"
1372 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1373 "}\n"
1374 "#endif // VERTEX_SHADER\n"
1375 "\n"
1376 "#ifdef FRAGMENT_SHADER\n"
1377 "void main(void)\n"
1378 "{\n"
1379 "#ifdef USEOFFSETMAPPING\n"
1380 "       // apply offsetmapping\n"
1381 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1382 "#define TexCoord TexCoordOffset\n"
1383 "#endif\n"
1384 "\n"
1385 "#ifdef USEALPHAKILL\n"
1386 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1387 "               discard;\n"
1388 "#endif\n"
1389 "\n"
1390 "#ifdef USEVERTEXTEXTUREBLEND\n"
1391 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1392 "       float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1393 "       //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
1394 "       //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
1395 "#endif\n"
1396 "\n"
1397 "#ifdef USEVERTEXTEXTUREBLEND\n"
1398 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1399 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1400 "#else\n"
1401 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1402 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1403 "#endif\n"
1404 "\n"
1405 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1406 "}\n"
1407 "#endif // FRAGMENT_SHADER\n"
1408 "#else // !MODE_DEFERREDGEOMETRY\n"
1409 "\n"
1410 "\n"
1411 "\n"
1412 "\n"
1413 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1414 "#ifdef VERTEX_SHADER\n"
1415 "uniform highp mat4 ModelViewMatrix;\n"
1416 "void main(void)\n"
1417 "{\n"
1418 "       ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1419 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1420 "}\n"
1421 "#endif // VERTEX_SHADER\n"
1422 "\n"
1423 "#ifdef FRAGMENT_SHADER\n"
1424 "uniform highp mat4 ViewToLight;\n"
1425 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1426 "uniform highp vec2 ScreenToDepth;\n"
1427 "uniform myhalf3 DeferredColor_Ambient;\n"
1428 "uniform myhalf3 DeferredColor_Diffuse;\n"
1429 "#ifdef USESPECULAR\n"
1430 "uniform myhalf3 DeferredColor_Specular;\n"
1431 "uniform myhalf SpecularPower;\n"
1432 "#endif\n"
1433 "uniform myhalf2 PixelToScreenTexCoord;\n"
1434 "void main(void)\n"
1435 "{\n"
1436 "       // calculate viewspace pixel position\n"
1437 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1438 "       vec3 position;\n"
1439 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1440 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1441 "       // decode viewspace pixel normal\n"
1442 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1443 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1444 "       // surfacenormal = pixel normal in viewspace\n"
1445 "       // LightVector = pixel to light in viewspace\n"
1446 "       // CubeVector = position in lightspace\n"
1447 "       // eyevector = pixel to view in viewspace\n"
1448 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1449 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1450 "#ifdef USEDIFFUSE\n"
1451 "       // calculate diffuse shading\n"
1452 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1453 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1454 "#endif\n"
1455 "#ifdef USESPECULAR\n"
1456 "       // calculate directional shading\n"
1457 "       vec3 eyevector = position * -1.0;\n"
1458 "#  ifdef USEEXACTSPECULARMATH\n"
1459 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1460 "#  else\n"
1461 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1462 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1463 "#  endif\n"
1464 "#endif\n"
1465 "\n"
1466 "#if defined(USESHADOWMAP2D)\n"
1467 "       fade *= ShadowMapCompare(CubeVector);\n"
1468 "#endif\n"
1469 "\n"
1470 "#ifdef USEDIFFUSE\n"
1471 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1472 "#else\n"
1473 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1474 "#endif\n"
1475 "#ifdef USESPECULAR\n"
1476 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1477 "#else\n"
1478 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1479 "#endif\n"
1480 "\n"
1481 "# ifdef USECUBEFILTER\n"
1482 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1483 "       gl_FragData[0].rgb *= cubecolor;\n"
1484 "       gl_FragData[1].rgb *= cubecolor;\n"
1485 "# endif\n"
1486 "}\n"
1487 "#endif // FRAGMENT_SHADER\n"
1488 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1489 "\n"
1490 "\n"
1491 "\n"
1492 "\n"
1493 "#ifdef VERTEX_SHADER\n"
1494 "uniform highp mat4 TexMatrix;\n"
1495 "#ifdef USEVERTEXTEXTUREBLEND\n"
1496 "uniform highp mat4 BackgroundTexMatrix;\n"
1497 "#endif\n"
1498 "#ifdef MODE_LIGHTSOURCE\n"
1499 "uniform highp mat4 ModelToLight;\n"
1500 "#endif\n"
1501 "#ifdef USESHADOWMAPORTHO\n"
1502 "uniform highp mat4 ShadowMapMatrix;\n"
1503 "#endif\n"
1504 "#ifdef USEBOUNCEGRID\n"
1505 "uniform highp mat4 BounceGridMatrix;\n"
1506 "#endif\n"
1507 "void main(void)\n"
1508 "{\n"
1509 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1510 "       VertexColor = Attrib_Color;\n"
1511 "#endif\n"
1512 "       // copy the surface texcoord\n"
1513 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1514 "#ifdef USEVERTEXTEXTUREBLEND\n"
1515 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1516 "#endif\n"
1517 "#ifdef USELIGHTMAP\n"
1518 "       TexCoordLightmap = vec2(Attrib_TexCoord4);\n"
1519 "#endif\n"
1520 "\n"
1521 "#ifdef USEBOUNCEGRID\n"
1522 "       BounceGridTexCoord = vec3(BounceGridMatrix * Attrib_Position);\n"
1523 "#endif\n"
1524 "\n"
1525 "#ifdef MODE_LIGHTSOURCE\n"
1526 "       // transform vertex position into light attenuation/cubemap space\n"
1527 "       // (-1 to +1 across the light box)\n"
1528 "       CubeVector = vec3(ModelToLight * Attrib_Position);\n"
1529 "\n"
1530 "# ifdef USEDIFFUSE\n"
1531 "       // transform unnormalized light direction into tangent space\n"
1532 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1533 "       //  normalize it per pixel)\n"
1534 "       vec3 lightminusvertex = LightPosition - Attrib_Position.xyz;\n"
1535 "       LightVector.x = dot(lightminusvertex, Attrib_TexCoord1.xyz);\n"
1536 "       LightVector.y = dot(lightminusvertex, Attrib_TexCoord2.xyz);\n"
1537 "       LightVector.z = dot(lightminusvertex, Attrib_TexCoord3.xyz);\n"
1538 "# endif\n"
1539 "#endif\n"
1540 "\n"
1541 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1542 "       LightVector.x = dot(LightDir, Attrib_TexCoord1.xyz);\n"
1543 "       LightVector.y = dot(LightDir, Attrib_TexCoord2.xyz);\n"
1544 "       LightVector.z = dot(LightDir, Attrib_TexCoord3.xyz);\n"
1545 "#endif\n"
1546 "\n"
1547 "       // transform unnormalized eye direction into tangent space\n"
1548 "#ifdef USEEYEVECTOR\n"
1549 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1550 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1551 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1552 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1553 "#endif\n"
1554 "\n"
1555 "#ifdef USEFOG\n"
1556 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - Attrib_Position.xyz;\n"
1557 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, Attrib_Position);\n"
1558 "#endif\n"
1559 "\n"
1560 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1561 "       VectorS = Attrib_TexCoord1.xyz;\n"
1562 "       VectorT = Attrib_TexCoord2.xyz;\n"
1563 "       VectorR = Attrib_TexCoord3.xyz;\n"
1564 "#endif\n"
1565 "\n"
1566 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1567 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1568 "\n"
1569 "#ifdef USESHADOWMAPORTHO\n"
1570 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1571 "#endif\n"
1572 "\n"
1573 "#ifdef USEREFLECTION\n"
1574 "       ModelViewProjectionPosition = gl_Position;\n"
1575 "#endif\n"
1576 "}\n"
1577 "#endif // VERTEX_SHADER\n"
1578 "\n"
1579 "\n"
1580 "\n"
1581 "\n"
1582 "#ifdef FRAGMENT_SHADER\n"
1583 "#ifdef USEDEFERREDLIGHTMAP\n"
1584 "uniform myhalf2 PixelToScreenTexCoord;\n"
1585 "uniform myhalf3 DeferredMod_Diffuse;\n"
1586 "uniform myhalf3 DeferredMod_Specular;\n"
1587 "#endif\n"
1588 "uniform myhalf3 Color_Ambient;\n"
1589 "uniform myhalf3 Color_Diffuse;\n"
1590 "uniform myhalf3 Color_Specular;\n"
1591 "uniform myhalf SpecularPower;\n"
1592 "#ifdef USEGLOW\n"
1593 "uniform myhalf3 Color_Glow;\n"
1594 "#endif\n"
1595 "uniform myhalf Alpha;\n"
1596 "#ifdef USEREFLECTION\n"
1597 "uniform mediump vec4 DistortScaleRefractReflect;\n"
1598 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
1599 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
1600 "uniform lowp vec4 ReflectColor;\n"
1601 "#endif\n"
1602 "#ifdef USEREFLECTCUBE\n"
1603 "uniform highp mat4 ModelToReflectCube;\n"
1604 "uniform sampler2D Texture_ReflectMask;\n"
1605 "uniform samplerCube Texture_ReflectCube;\n"
1606 "#endif\n"
1607 "#ifdef MODE_LIGHTDIRECTION\n"
1608 "uniform myhalf3 LightColor;\n"
1609 "#endif\n"
1610 "#ifdef MODE_LIGHTSOURCE\n"
1611 "uniform myhalf3 LightColor;\n"
1612 "#endif\n"
1613 "#ifdef USEBOUNCEGRID\n"
1614 "uniform sampler3D Texture_BounceGrid;\n"
1615 "uniform float BounceGridIntensity;\n"
1616 "#endif\n"
1617 "void main(void)\n"
1618 "{\n"
1619 "#ifdef USEOFFSETMAPPING\n"
1620 "       // apply offsetmapping\n"
1621 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1622 "#define TexCoord TexCoordOffset\n"
1623 "#endif\n"
1624 "\n"
1625 "       // combine the diffuse textures (base, pants, shirt)\n"
1626 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1627 "#ifdef USEALPHAKILL\n"
1628 "       if (color.a < 0.5)\n"
1629 "               discard;\n"
1630 "#endif\n"
1631 "       color.a *= Alpha;\n"
1632 "#ifdef USECOLORMAPPING\n"
1633 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1634 "#endif\n"
1635 "#ifdef USEVERTEXTEXTUREBLEND\n"
1636 "       myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1637 "       //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
1638 "       //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
1639 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1640 "       color.a = 1.0;\n"
1641 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1642 "#endif\n"
1643 "\n"
1644 "       // get the surface normal\n"
1645 "#ifdef USEVERTEXTEXTUREBLEND\n"
1646 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1647 "#else\n"
1648 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1649 "#endif\n"
1650 "\n"
1651 "       // get the material colors\n"
1652 "       myhalf3 diffusetex = color.rgb;\n"
1653 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1654 "# ifdef USEVERTEXTEXTUREBLEND\n"
1655 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1656 "# else\n"
1657 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1658 "# endif\n"
1659 "#endif\n"
1660 "\n"
1661 "#ifdef USEREFLECTCUBE\n"
1662 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1663 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1664 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1665 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1666 "#endif\n"
1667 "\n"
1668 "\n"
1669 "\n"
1670 "\n"
1671 "#ifdef MODE_LIGHTSOURCE\n"
1672 "       // light source\n"
1673 "#ifdef USEDIFFUSE\n"
1674 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1675 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1676 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1677 "#ifdef USESPECULAR\n"
1678 "#ifdef USEEXACTSPECULARMATH\n"
1679 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1680 "#else\n"
1681 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1682 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1683 "#endif\n"
1684 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1685 "#endif\n"
1686 "#else\n"
1687 "       color.rgb = diffusetex * Color_Ambient;\n"
1688 "#endif\n"
1689 "       color.rgb *= LightColor;\n"
1690 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1691 "#if defined(USESHADOWMAP2D)\n"
1692 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1693 "#endif\n"
1694 "# ifdef USECUBEFILTER\n"
1695 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1696 "# endif\n"
1697 "#endif // MODE_LIGHTSOURCE\n"
1698 "\n"
1699 "\n"
1700 "\n"
1701 "\n"
1702 "#ifdef MODE_LIGHTDIRECTION\n"
1703 "#define SHADING\n"
1704 "#ifdef USEDIFFUSE\n"
1705 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1706 "#endif\n"
1707 "#define lightcolor LightColor\n"
1708 "#endif // MODE_LIGHTDIRECTION\n"
1709 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1710 "#define SHADING\n"
1711 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1712 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1713 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1714 "       // convert modelspace light vector to tangentspace\n"
1715 "       myhalf3 lightnormal;\n"
1716 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1717 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1718 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1719 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1720 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1721 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1722 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1723 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1724 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1725 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1726 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1727 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1728 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1729 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1730 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1731 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1732 "#define SHADING\n"
1733 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1734 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1735 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1736 "#endif\n"
1737 "\n"
1738 "\n"
1739 "\n"
1740 "\n"
1741 "#ifdef MODE_FAKELIGHT\n"
1742 "#define SHADING\n"
1743 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1744 "myhalf3 lightcolor = myhalf3(1.0);\n"
1745 "#endif // MODE_FAKELIGHT\n"
1746 "\n"
1747 "\n"
1748 "\n"
1749 "\n"
1750 "#ifdef MODE_LIGHTMAP\n"
1751 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1752 "#endif // MODE_LIGHTMAP\n"
1753 "#ifdef MODE_VERTEXCOLOR\n"
1754 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
1755 "#endif // MODE_VERTEXCOLOR\n"
1756 "#ifdef MODE_FLATCOLOR\n"
1757 "       color.rgb = diffusetex * Color_Ambient;\n"
1758 "#endif // MODE_FLATCOLOR\n"
1759 "\n"
1760 "\n"
1761 "\n"
1762 "\n"
1763 "#ifdef SHADING\n"
1764 "# ifdef USEDIFFUSE\n"
1765 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1766 "#  ifdef USESPECULAR\n"
1767 "#   ifdef USEEXACTSPECULARMATH\n"
1768 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1769 "#   else\n"
1770 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1771 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1772 "#   endif\n"
1773 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1774 "#  else\n"
1775 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1776 "#  endif\n"
1777 "# else\n"
1778 "       color.rgb = diffusetex * Color_Ambient;\n"
1779 "# endif\n"
1780 "#endif\n"
1781 "\n"
1782 "#ifdef USESHADOWMAPORTHO\n"
1783 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1784 "#endif\n"
1785 "\n"
1786 "#ifdef USEDEFERREDLIGHTMAP\n"
1787 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1788 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1789 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1790 "#endif\n"
1791 "\n"
1792 "#ifdef USEBOUNCEGRID\n"
1793 "       color.rgb += diffusetex * myhalf3(texture3D(Texture_BounceGrid, BounceGridTexCoord)) * BounceGridIntensity;\n"
1794 "#endif\n"
1795 "\n"
1796 "#ifdef USEGLOW\n"
1797 "#ifdef USEVERTEXTEXTUREBLEND\n"
1798 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1799 "#else\n"
1800 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1801 "#endif\n"
1802 "#endif\n"
1803 "\n"
1804 "#ifdef USEFOG\n"
1805 "       color.rgb = FogVertex(color.rgb);\n"
1806 "#endif\n"
1807 "\n"
1808 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1809 "#ifdef USEREFLECTION\n"
1810 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1811 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1812 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1813 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1814 "       // FIXME temporary hack to detect the case that the reflection\n"
1815 "       // gets blackened at edges due to leaving the area that contains actual\n"
1816 "       // content.\n"
1817 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1818 "       // 'appening.\n"
1819 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1820 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1821 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1822 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1823 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1824 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1825 "#endif\n"
1826 "\n"
1827 "       gl_FragColor = vec4(color);\n"
1828 "}\n"
1829 "#endif // FRAGMENT_SHADER\n"
1830 "\n"
1831 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1832 "#endif // !MODE_DEFERREDGEOMETRY\n"
1833 "#endif // !MODE_WATER\n"
1834 "#endif // !MODE_REFRACTION\n"
1835 "#endif // !MODE_BLOOMBLUR\n"
1836 "#endif // !MODE_GENERIC\n"
1837 "#endif // !MODE_POSTPROCESS\n"
1838 "#endif // !MODE_SHOWDEPTH\n"
1839 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1840 ;
1841
1842 /*
1843 =========================================================================================================================================================
1844
1845
1846
1847 =========================================================================================================================================================
1848
1849
1850
1851 =========================================================================================================================================================
1852
1853
1854
1855 =========================================================================================================================================================
1856
1857
1858
1859 =========================================================================================================================================================
1860
1861
1862
1863 =========================================================================================================================================================
1864
1865
1866
1867 =========================================================================================================================================================
1868 */
1869
1870 const char *builtinhlslshaderstring =
1871 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1872 "// written by Forest 'LordHavoc' Hale\n"
1873 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1874 "\n"
1875 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1876 "#if defined(USEREFLECTION)\n"
1877 "#undef USESHADOWMAPORTHO\n"
1878 "#endif\n"
1879 "\n"
1880 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1881 "# define USEFOG\n"
1882 "#endif\n"
1883 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1884 "#define USELIGHTMAP\n"
1885 "#endif\n"
1886 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1887 "#define USEEYEVECTOR\n"
1888 "#endif\n"
1889 "\n"
1890 "#ifdef FRAGMENT_SHADER\n"
1891 "#ifdef HLSL\n"
1892 "//#undef USESHADOWMAPPCF\n"
1893 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1894 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1895 "#else\n"
1896 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1897 "#endif\n"
1898 "#endif\n"
1899 "\n"
1900 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1901 "#ifdef VERTEX_SHADER\n"
1902 "void main\n"
1903 "(\n"
1904 "float4 gl_Vertex : POSITION,\n"
1905 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1906 "out float4 gl_Position : POSITION,\n"
1907 "out float Depth : TEXCOORD0\n"
1908 ")\n"
1909 "{\n"
1910 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1911 "       Depth = gl_Position.z;\n"
1912 "}\n"
1913 "#endif\n"
1914 "\n"
1915 "#ifdef FRAGMENT_SHADER\n"
1916 "void main\n"
1917 "(\n"
1918 "float Depth : TEXCOORD0,\n"
1919 "out float4 gl_FragColor : COLOR\n"
1920 ")\n"
1921 "{\n"
1922 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1923 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1924 "       temp.yz -= floor(temp.yz);\n"
1925 "       gl_FragColor = temp;\n"
1926 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1927 "}\n"
1928 "#endif\n"
1929 "#else // !MODE_DEPTH_ORSHADOW\n"
1930 "\n"
1931 "\n"
1932 "\n"
1933 "\n"
1934 "#ifdef MODE_SHOWDEPTH\n"
1935 "#ifdef VERTEX_SHADER\n"
1936 "void main\n"
1937 "(\n"
1938 "float4 gl_Vertex : POSITION,\n"
1939 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1940 "out float4 gl_Position : POSITION,\n"
1941 "out float4 gl_FrontColor : COLOR0\n"
1942 ")\n"
1943 "{\n"
1944 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1945 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1946 "}\n"
1947 "#endif\n"
1948 "\n"
1949 "#ifdef FRAGMENT_SHADER\n"
1950 "void main\n"
1951 "(\n"
1952 "float4 gl_FrontColor : COLOR0,\n"
1953 "out float4 gl_FragColor : COLOR\n"
1954 ")\n"
1955 "{\n"
1956 "       gl_FragColor = gl_FrontColor;\n"
1957 "}\n"
1958 "#endif\n"
1959 "#else // !MODE_SHOWDEPTH\n"
1960 "\n"
1961 "\n"
1962 "\n"
1963 "\n"
1964 "#ifdef MODE_POSTPROCESS\n"
1965 "\n"
1966 "#ifdef VERTEX_SHADER\n"
1967 "void main\n"
1968 "(\n"
1969 "float4 gl_Vertex : POSITION,\n"
1970 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1971 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1972 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1973 "out float4 gl_Position : POSITION,\n"
1974 "out float2 TexCoord1 : TEXCOORD0,\n"
1975 "out float2 TexCoord2 : TEXCOORD1\n"
1976 ")\n"
1977 "{\n"
1978 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1979 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1980 "#ifdef USEBLOOM\n"
1981 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1982 "#endif\n"
1983 "}\n"
1984 "#endif\n"
1985 "\n"
1986 "#ifdef FRAGMENT_SHADER\n"
1987 "void main\n"
1988 "(\n"
1989 "float2 TexCoord1 : TEXCOORD0,\n"
1990 "float2 TexCoord2 : TEXCOORD1,\n"
1991 "uniform sampler Texture_First : register(s0),\n"
1992 "#ifdef USEBLOOM\n"
1993 "uniform sampler Texture_Second : register(s1),\n"
1994 "#endif\n"
1995 "#ifdef USEGAMMARAMPS\n"
1996 "uniform sampler Texture_GammaRamps : register(s2),\n"
1997 "#endif\n"
1998 "#ifdef USESATURATION\n"
1999 "uniform float Saturation : register(c30),\n"
2000 "#endif\n"
2001 "#ifdef USEVIEWTINT\n"
2002 "uniform float4 ViewTintColor : register(c41),\n"
2003 "#endif\n"
2004 "uniform float4 UserVec1 : register(c37),\n"
2005 "uniform float4 UserVec2 : register(c38),\n"
2006 "uniform float4 UserVec3 : register(c39),\n"
2007 "uniform float4 UserVec4 : register(c40),\n"
2008 "uniform float ClientTime : register(c2),\n"
2009 "uniform float2 PixelSize : register(c25),\n"
2010 "uniform float4 BloomColorSubtract : register(c43),\n"
2011 "out float4 gl_FragColor : COLOR\n"
2012 ")\n"
2013 "{\n"
2014 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2015 "#ifdef USEBLOOM\n"
2016 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2017 "#endif\n"
2018 "#ifdef USEVIEWTINT\n"
2019 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2020 "#endif\n"
2021 "\n"
2022 "#ifdef USEPOSTPROCESSING\n"
2023 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2024 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
2025 "       float sobel = 1.0;\n"
2026 "       // float2 ts = textureSize(Texture_First, 0);\n"
2027 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
2028 "       float2 px = PixelSize;\n"
2029 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2030 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
2031 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2032 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2033 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
2034 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2035 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2036 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
2037 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2038 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2039 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
2040 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2041 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2042 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2043 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2044 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2045 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2046 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2047 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2048 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2049 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2050 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2051 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2052 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2053 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2054 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2055 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2056 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2057 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2058 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2059 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2060 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2061 "#endif\n"
2062 "\n"
2063 "#ifdef USESATURATION\n"
2064 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2065 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2066 "       // 'vampire sight' effect, wheres red is compensated\n"
2067 "       #ifdef SATURATION_REDCOMPENSATE\n"
2068 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2069 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2070 "               gl_FragColor.r += r;\n"
2071 "       #else\n"
2072 "               // normal desaturation\n"
2073 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2074 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2075 "       #endif\n"
2076 "#endif\n"
2077 "\n"
2078 "#ifdef USEGAMMARAMPS\n"
2079 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2080 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2081 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2082 "#endif\n"
2083 "}\n"
2084 "#endif\n"
2085 "#else // !MODE_POSTPROCESS\n"
2086 "\n"
2087 "\n"
2088 "\n"
2089 "\n"
2090 "#ifdef MODE_GENERIC\n"
2091 "#ifdef VERTEX_SHADER\n"
2092 "void main\n"
2093 "(\n"
2094 "float4 gl_Vertex : POSITION,\n"
2095 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2096 "float4 gl_Color : COLOR0,\n"
2097 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2098 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2099 "out float4 gl_Position : POSITION,\n"
2100 "#ifdef USEDIFFUSE\n"
2101 "out float2 TexCoord1 : TEXCOORD0,\n"
2102 "#endif\n"
2103 "#ifdef USESPECULAR\n"
2104 "out float2 TexCoord2 : TEXCOORD1,\n"
2105 "#endif\n"
2106 "out float4 gl_FrontColor : COLOR\n"
2107 ")\n"
2108 "{\n"
2109 "       gl_FrontColor = gl_Color;\n"
2110 "#ifdef USEDIFFUSE\n"
2111 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2112 "#endif\n"
2113 "#ifdef USESPECULAR\n"
2114 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2115 "#endif\n"
2116 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2117 "}\n"
2118 "#endif\n"
2119 "\n"
2120 "#ifdef FRAGMENT_SHADER\n"
2121 "\n"
2122 "void main\n"
2123 "(\n"
2124 "float4 gl_FrontColor : COLOR0,\n"
2125 "float2 TexCoord1 : TEXCOORD0,\n"
2126 "float2 TexCoord2 : TEXCOORD1,\n"
2127 "#ifdef USEDIFFUSE\n"
2128 "uniform sampler Texture_First : register(s0),\n"
2129 "#endif\n"
2130 "#ifdef USESPECULAR\n"
2131 "uniform sampler Texture_Second : register(s1),\n"
2132 "#endif\n"
2133 "out float4 gl_FragColor : COLOR\n"
2134 ")\n"
2135 "{\n"
2136 "#ifdef USEVIEWTINT\n"
2137 "       gl_FragColor = gl_FrontColor;\n"
2138 "#else\n"
2139 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2140 "#endif\n"
2141 "#ifdef USEDIFFUSE\n"
2142 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2143 "#endif\n"
2144 "\n"
2145 "#ifdef USESPECULAR\n"
2146 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2147 "# ifdef USECOLORMAPPING\n"
2148 "       gl_FragColor *= tex2;\n"
2149 "# endif\n"
2150 "# ifdef USEGLOW\n"
2151 "       gl_FragColor += tex2;\n"
2152 "# endif\n"
2153 "# ifdef USEVERTEXTEXTUREBLEND\n"
2154 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2155 "# endif\n"
2156 "#endif\n"
2157 "}\n"
2158 "#endif\n"
2159 "#else // !MODE_GENERIC\n"
2160 "\n"
2161 "\n"
2162 "\n"
2163 "\n"
2164 "#ifdef MODE_BLOOMBLUR\n"
2165 "#ifdef VERTEX_SHADER\n"
2166 "void main\n"
2167 "(\n"
2168 "float4 gl_Vertex : POSITION,\n"
2169 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2170 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2171 "out float4 gl_Position : POSITION,\n"
2172 "out float2 TexCoord : TEXCOORD0\n"
2173 ")\n"
2174 "{\n"
2175 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2176 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2177 "}\n"
2178 "#endif\n"
2179 "\n"
2180 "#ifdef FRAGMENT_SHADER\n"
2181 "\n"
2182 "void main\n"
2183 "(\n"
2184 "float2 TexCoord : TEXCOORD0,\n"
2185 "uniform sampler Texture_First : register(s0),\n"
2186 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2187 "out float4 gl_FragColor : COLOR\n"
2188 ")\n"
2189 "{\n"
2190 "       int i;\n"
2191 "       float2 tc = TexCoord;\n"
2192 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2193 "       tc += BloomBlur_Parameters.xy;\n"
2194 "       for (i = 1;i < SAMPLES;i++)\n"
2195 "       {\n"
2196 "               color += tex2D(Texture_First, tc).rgb;\n"
2197 "               tc += BloomBlur_Parameters.xy;\n"
2198 "       }\n"
2199 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2200 "}\n"
2201 "#endif\n"
2202 "#else // !MODE_BLOOMBLUR\n"
2203 "#ifdef MODE_REFRACTION\n"
2204 "#ifdef VERTEX_SHADER\n"
2205 "void main\n"
2206 "(\n"
2207 "float4 gl_Vertex : POSITION,\n"
2208 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2209 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2210 "uniform float4x4 TexMatrix : register(c0),\n"
2211 "uniform float3 EyePosition : register(c24),\n"
2212 "out float4 gl_Position : POSITION,\n"
2213 "out float2 TexCoord : TEXCOORD0,\n"
2214 "out float3 EyeVector : TEXCOORD1,\n"
2215 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2216 ")\n"
2217 "{\n"
2218 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2219 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2220 "       ModelViewProjectionPosition = gl_Position;\n"
2221 "}\n"
2222 "#endif\n"
2223 "\n"
2224 "#ifdef FRAGMENT_SHADER\n"
2225 "void main\n"
2226 "(\n"
2227 "float2 TexCoord : TEXCOORD0,\n"
2228 "float3 EyeVector : TEXCOORD1,\n"
2229 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2230 "uniform sampler Texture_Normal : register(s0),\n"
2231 "uniform sampler Texture_Refraction : register(s3),\n"
2232 "uniform sampler Texture_Reflection : register(s7),\n"
2233 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2234 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2235 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2236 "uniform float4 RefractColor : register(c29),\n"
2237 "out float4 gl_FragColor : COLOR\n"
2238 ")\n"
2239 "{\n"
2240 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2241 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2242 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2243 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2244 "       // FIXME temporary hack to detect the case that the reflection\n"
2245 "       // gets blackened at edges due to leaving the area that contains actual\n"
2246 "       // content.\n"
2247 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2248 "       // 'appening.\n"
2249 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2250 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2251 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2252 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2253 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2254 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2255 "}\n"
2256 "#endif\n"
2257 "#else // !MODE_REFRACTION\n"
2258 "\n"
2259 "\n"
2260 "\n"
2261 "\n"
2262 "#ifdef MODE_WATER\n"
2263 "#ifdef VERTEX_SHADER\n"
2264 "\n"
2265 "void main\n"
2266 "(\n"
2267 "float4 gl_Vertex : POSITION,\n"
2268 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2269 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2270 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2271 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2272 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2273 "uniform float4x4 TexMatrix : register(c0),\n"
2274 "uniform float3 EyePosition : register(c24),\n"
2275 "out float4 gl_Position : POSITION,\n"
2276 "out float2 TexCoord : TEXCOORD0,\n"
2277 "out float3 EyeVector : TEXCOORD1,\n"
2278 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2279 ")\n"
2280 "{\n"
2281 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2282 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2283 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2284 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2285 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2286 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2287 "       ModelViewProjectionPosition = gl_Position;\n"
2288 "}\n"
2289 "#endif\n"
2290 "\n"
2291 "#ifdef FRAGMENT_SHADER\n"
2292 "void main\n"
2293 "(\n"
2294 "float2 TexCoord : TEXCOORD0,\n"
2295 "float3 EyeVector : TEXCOORD1,\n"
2296 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2297 "uniform sampler Texture_Normal : register(s0),\n"
2298 "uniform sampler Texture_Refraction : register(s3),\n"
2299 "uniform sampler Texture_Reflection : register(s7),\n"
2300 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2301 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2302 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2303 "uniform float4 RefractColor : register(c29),\n"
2304 "uniform float4 ReflectColor : register(c26),\n"
2305 "uniform float ReflectFactor : register(c27),\n"
2306 "uniform float ReflectOffset : register(c28),\n"
2307 "out float4 gl_FragColor : COLOR\n"
2308 ")\n"
2309 "{\n"
2310 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2311 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2312 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2313 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2314 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2315 "       // FIXME temporary hack to detect the case that the reflection\n"
2316 "       // gets blackened at edges due to leaving the area that contains actual\n"
2317 "       // content.\n"
2318 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2319 "       // 'appening.\n"
2320 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2321 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2322 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2323 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2324 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2325 "       f  = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2326 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2327 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2328 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2329 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2330 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2331 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2332 "}\n"
2333 "#endif\n"
2334 "#else // !MODE_WATER\n"
2335 "\n"
2336 "\n"
2337 "\n"
2338 "\n"
2339 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2340 "\n"
2341 "// fragment shader specific:\n"
2342 "#ifdef FRAGMENT_SHADER\n"
2343 "\n"
2344 "#ifdef USEFOG\n"
2345 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2346 "{\n"
2347 "       float fogfrac;\n"
2348 "#ifdef USEFOGHEIGHTTEXTURE\n"
2349 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2350 "       fogfrac = fogheightpixel.a;\n"
2351 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2352 "#else\n"
2353 "# ifdef USEFOGOUTSIDE\n"
2354 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2355 "# else\n"
2356 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2357 "# endif\n"
2358 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2359 "#endif\n"
2360 "}\n"
2361 "#endif\n"
2362 "\n"
2363 "#ifdef USEOFFSETMAPPING\n"
2364 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2365 "{\n"
2366 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2367 "       // 14 sample relief mapping: linear search and then binary search\n"
2368 "       // this basically steps forward a small amount repeatedly until it finds\n"
2369 "       // itself inside solid, then jitters forward and back using decreasing\n"
2370 "       // amounts to find the impact\n"
2371 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2372 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2373 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2374 "       float3 RT = float3(TexCoord, 1);\n"
2375 "       OffsetVector *= 0.1;\n"
2376 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2377 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2378 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2379 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2380 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2381 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2382 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2383 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2384 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2385 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2386 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2387 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2388 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2389 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2390 "       return RT.xy;\n"
2391 "#else\n"
2392 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2393 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2394 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2395 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2396 "       OffsetVector *= 0.5;\n"
2397 "       TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
2398 "       TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
2399 "       return TexCoord;\n"
2400 "#endif\n"
2401 "}\n"
2402 "#endif // USEOFFSETMAPPING\n"
2403 "\n"
2404 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2405 "#if defined(USESHADOWMAP2D)\n"
2406 "# ifdef USESHADOWMAPORTHO\n"
2407 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2408 "# else\n"
2409 "#  ifdef USESHADOWMAPVSDCT\n"
2410 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2411 "{\n"
2412 "       float3 adir = abs(dir);\n"
2413 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2414 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2415 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2416 "}\n"
2417 "#  else\n"
2418 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2419 "{\n"
2420 "       float3 adir = abs(dir);\n"
2421 "       float ma = adir.z;\n"
2422 "       float4 proj = float4(dir, 2.5);\n"
2423 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2424 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2425 "#ifdef HLSL\n"
2426 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2427 "#else\n"
2428 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2429 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2430 "#endif\n"
2431 "}\n"
2432 "#  endif\n"
2433 "# endif\n"
2434 "#endif // defined(USESHADOWMAP2D)\n"
2435 "\n"
2436 "# ifdef USESHADOWMAP2D\n"
2437 "#ifdef USESHADOWMAPVSDCT\n"
2438 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2439 "#else\n"
2440 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2441 "#endif\n"
2442 "{\n"
2443 "#ifdef USESHADOWMAPVSDCT\n"
2444 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2445 "#else\n"
2446 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2447 "#endif\n"
2448 "       float f;\n"
2449 "\n"
2450 "#  ifdef USESHADOWSAMPLER\n"
2451 "#    ifdef USESHADOWMAPPCF\n"
2452 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2453 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2454 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2455 "#    else\n"
2456 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2457 "#    endif\n"
2458 "#  else\n"
2459 "#    ifdef USESHADOWMAPPCF\n"
2460 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2461 "#      ifdef GL_ARB_texture_gather\n"
2462 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2463 "#      else\n"
2464 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2465 "#      endif\n"
2466 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2467 "#      if USESHADOWMAPPCF > 1\n"
2468 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2469 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2470 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2471 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2472 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2473 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2474 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2475 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2476 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2477 "       float4 locols = float4(group1.ab, group3.ab);\n"
2478 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2479 "       locols.yz += group2.ab;\n"
2480 "       hicols.yz += group8.rg;\n"
2481 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2482 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2483 "                               lerp(locols, hicols, offset.y);\n"
2484 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2485 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2486 "       f = dot(cols, float4(1.0/25.0));\n"
2487 "#      else\n"
2488 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2489 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2490 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2491 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2492 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2493 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2494 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2495 "#      endif\n"
2496 "#     else\n"
2497 "#      ifdef GL_EXT_gpu_shader4\n"
2498 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2499 "#      else\n"
2500 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2501 "#      endif\n"
2502 "#      if USESHADOWMAPPCF > 1\n"
2503 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2504 "       center *= ShadowMap_TextureScale;\n"
2505 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2506 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2507 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2508 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2509 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2510 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2511 "#      else\n"
2512 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2513 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2514 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2515 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2516 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2517 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2518 "#      endif\n"
2519 "#     endif\n"
2520 "#    else\n"
2521 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2522 "#    endif\n"
2523 "#  endif\n"
2524 "#  ifdef USESHADOWMAPORTHO\n"
2525 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2526 "#  else\n"
2527 "       return f;\n"
2528 "#  endif\n"
2529 "}\n"
2530 "# endif\n"
2531 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2532 "#endif // FRAGMENT_SHADER\n"
2533 "\n"
2534 "\n"
2535 "\n"
2536 "\n"
2537 "#ifdef MODE_DEFERREDGEOMETRY\n"
2538 "#ifdef VERTEX_SHADER\n"
2539 "void main\n"
2540 "(\n"
2541 "float4 gl_Vertex : POSITION,\n"
2542 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2543 "#ifdef USEVERTEXTEXTUREBLEND\n"
2544 "float4 gl_Color : COLOR0,\n"
2545 "#endif\n"
2546 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2547 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2548 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2549 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2550 "uniform float4x4 TexMatrix : register(c0),\n"
2551 "#ifdef USEVERTEXTEXTUREBLEND\n"
2552 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2553 "#endif\n"
2554 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2555 "#ifdef USEOFFSETMAPPING\n"
2556 "uniform float3 EyePosition : register(c24),\n"
2557 "#endif\n"
2558 "out float4 gl_Position : POSITION,\n"
2559 "#ifdef USEVERTEXTEXTUREBLEND\n"
2560 "out float4 gl_FrontColor : COLOR,\n"
2561 "#endif\n"
2562 "out float4 TexCoordBoth : TEXCOORD0,\n"
2563 "#ifdef USEOFFSETMAPPING\n"
2564 "out float3 EyeVector : TEXCOORD2,\n"
2565 "#endif\n"
2566 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2567 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2568 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2569 ")\n"
2570 "{\n"
2571 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2572 "#ifdef USEVERTEXTEXTUREBLEND\n"
2573 "       gl_FrontColor = gl_Color;\n"
2574 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2575 "#endif\n"
2576 "\n"
2577 "       // transform unnormalized eye direction into tangent space\n"
2578 "#ifdef USEOFFSETMAPPING\n"
2579 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2580 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2581 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2582 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2583 "#endif\n"
2584 "\n"
2585 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2586 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2587 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2588 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2589 "       VectorR.w = gl_Position.z;\n"
2590 "}\n"
2591 "#endif // VERTEX_SHADER\n"
2592 "\n"
2593 "#ifdef FRAGMENT_SHADER\n"
2594 "void main\n"
2595 "(\n"
2596 "float4 TexCoordBoth : TEXCOORD0,\n"
2597 "float3 EyeVector : TEXCOORD2,\n"
2598 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2599 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2600 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2601 "uniform sampler Texture_Normal : register(s0),\n"
2602 "#ifdef USEALPHAKILL\n"
2603 "uniform sampler Texture_Color : register(s1),\n"
2604 "#endif\n"
2605 "uniform sampler Texture_Gloss : register(s2),\n"
2606 "#ifdef USEVERTEXTEXTUREBLEND\n"
2607 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2608 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2609 "#endif\n"
2610 "#ifdef USEOFFSETMAPPING\n"
2611 "uniform float OffsetMapping_Scale : register(c24),\n"
2612 "#endif\n"
2613 "uniform half SpecularPower : register(c36),\n"
2614 "#ifdef HLSL\n"
2615 "out float4 gl_FragData0 : COLOR0,\n"
2616 "out float4 gl_FragData1 : COLOR1\n"
2617 "#else\n"
2618 "out float4 gl_FragColor : COLOR\n"
2619 "#endif\n"
2620 ")\n"
2621 "{\n"
2622 "       float2 TexCoord = TexCoordBoth.xy;\n"
2623 "#ifdef USEOFFSETMAPPING\n"
2624 "       // apply offsetmapping\n"
2625 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2626 "#define TexCoord TexCoordOffset\n"
2627 "#endif\n"
2628 "\n"
2629 "#ifdef USEALPHAKILL\n"
2630 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2631 "               discard;\n"
2632 "#endif\n"
2633 "\n"
2634 "#ifdef USEVERTEXTEXTUREBLEND\n"
2635 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2636 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2637 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2638 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2639 "#endif\n"
2640 "\n"
2641 "#ifdef USEVERTEXTEXTUREBLEND\n"
2642 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2643 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2644 "#else\n"
2645 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2646 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2647 "#endif\n"
2648 "\n"
2649 "#ifdef HLSL\n"
2650 "       gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2651 "       float Depth = VectorR.w / 256.0;\n"
2652 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2653 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2654 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2655 "       gl_FragData1 = depthcolor;\n"
2656 "#else\n"
2657 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2658 "#endif\n"
2659 "}\n"
2660 "#endif // FRAGMENT_SHADER\n"
2661 "#else // !MODE_DEFERREDGEOMETRY\n"
2662 "\n"
2663 "\n"
2664 "\n"
2665 "\n"
2666 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2667 "#ifdef VERTEX_SHADER\n"
2668 "void main\n"
2669 "(\n"
2670 "float4 gl_Vertex : POSITION,\n"
2671 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2672 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2673 "out float4 gl_Position : POSITION,\n"
2674 "out float4 ModelViewPosition : TEXCOORD0\n"
2675 ")\n"
2676 "{\n"
2677 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2678 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2679 "}\n"
2680 "#endif // VERTEX_SHADER\n"
2681 "\n"
2682 "#ifdef FRAGMENT_SHADER\n"
2683 "void main\n"
2684 "(\n"
2685 "#ifdef HLSL\n"
2686 "float2 Pixel : VPOS,\n"
2687 "#else\n"
2688 "float2 Pixel : WPOS,\n"
2689 "#endif\n"
2690 "float4 ModelViewPosition : TEXCOORD0,\n"
2691 "uniform float4x4 ViewToLight : register(c44),\n"
2692 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2693 "uniform float3 LightPosition : register(c23),\n"
2694 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2695 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2696 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2697 "#ifdef USESPECULAR\n"
2698 "uniform half3 DeferredColor_Specular : register(c11),\n"
2699 "uniform half SpecularPower : register(c36),\n"
2700 "#endif\n"
2701 "uniform sampler Texture_Attenuation : register(s9),\n"
2702 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2703 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2704 "\n"
2705 "#ifdef USECUBEFILTER\n"
2706 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2707 "#endif\n"
2708 "\n"
2709 "#ifdef USESHADOWMAP2D\n"
2710 "# ifdef USESHADOWSAMPLER\n"
2711 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2712 "# else\n"
2713 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2714 "# endif\n"
2715 "#endif\n"
2716 "\n"
2717 "#ifdef USESHADOWMAPVSDCT\n"
2718 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2719 "#endif\n"
2720 "\n"
2721 "#if defined(USESHADOWMAP2D)\n"
2722 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2723 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2724 "#endif\n"
2725 "\n"
2726 "out float4 gl_FragData0 : COLOR0,\n"
2727 "out float4 gl_FragData1 : COLOR1\n"
2728 ")\n"
2729 "{\n"
2730 "       // calculate viewspace pixel position\n"
2731 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2732 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2733 "       float3 position;\n"
2734 "#ifdef HLSL\n"
2735 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2736 "#else\n"
2737 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2738 "#endif\n"
2739 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2740 "       // decode viewspace pixel normal\n"
2741 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2742 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2743 "       // surfacenormal = pixel normal in viewspace\n"
2744 "       // LightVector = pixel to light in viewspace\n"
2745 "       // CubeVector = position in lightspace\n"
2746 "       // eyevector = pixel to view in viewspace\n"
2747 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2748 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2749 "#ifdef USEDIFFUSE\n"
2750 "       // calculate diffuse shading\n"
2751 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2752 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2753 "#endif\n"
2754 "#ifdef USESPECULAR\n"
2755 "       // calculate directional shading\n"
2756 "       float3 eyevector = position * -1.0;\n"
2757 "#  ifdef USEEXACTSPECULARMATH\n"
2758 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2759 "#  else\n"
2760 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2761 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2762 "#  endif\n"
2763 "#endif\n"
2764 "\n"
2765 "#if defined(USESHADOWMAP2D)\n"
2766 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2767 "#ifdef USESHADOWMAPVSDCT\n"
2768 ", Texture_CubeProjection\n"
2769 "#endif\n"
2770 "       ));\n"
2771 "#endif\n"
2772 "\n"
2773 "#ifdef USEDIFFUSE\n"
2774 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2775 "#else\n"
2776 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2777 "#endif\n"
2778 "#ifdef USESPECULAR\n"
2779 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2780 "#else\n"
2781 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2782 "#endif\n"
2783 "\n"
2784 "# ifdef USECUBEFILTER\n"
2785 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2786 "       gl_FragData0.rgb *= cubecolor;\n"
2787 "       gl_FragData1.rgb *= cubecolor;\n"
2788 "# endif\n"
2789 "}\n"
2790 "#endif // FRAGMENT_SHADER\n"
2791 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2792 "\n"
2793 "\n"
2794 "\n"
2795 "\n"
2796 "#ifdef VERTEX_SHADER\n"
2797 "void main\n"
2798 "(\n"
2799 "float4 gl_Vertex : POSITION,\n"
2800 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2801 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2802 "float4 gl_Color : COLOR0,\n"
2803 "#endif\n"
2804 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2805 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2806 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2807 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2808 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2809 "\n"
2810 "uniform float3 EyePosition : register(c24),\n"
2811 "uniform float4x4 TexMatrix : register(c0),\n"
2812 "#ifdef USEVERTEXTEXTUREBLEND\n"
2813 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2814 "#endif\n"
2815 "#ifdef MODE_LIGHTSOURCE\n"
2816 "uniform float4x4 ModelToLight : register(c20),\n"
2817 "#endif\n"
2818 "#ifdef MODE_LIGHTSOURCE\n"
2819 "uniform float3 LightPosition : register(c27),\n"
2820 "#endif\n"
2821 "#ifdef MODE_LIGHTDIRECTION\n"
2822 "uniform float3 LightDir : register(c26),\n"
2823 "#endif\n"
2824 "uniform float4 FogPlane : register(c25),\n"
2825 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2826 "uniform float3 LightPosition : register(c27),\n"
2827 "#endif\n"
2828 "#ifdef USESHADOWMAPORTHO\n"
2829 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2830 "#endif\n"
2831 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2832 "out float4 gl_FrontColor : COLOR,\n"
2833 "#endif\n"
2834 "out float4 TexCoordBoth : TEXCOORD0,\n"
2835 "#ifdef USELIGHTMAP\n"
2836 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2837 "#endif\n"
2838 "#ifdef USEEYEVECTOR\n"
2839 "out float3 EyeVector : TEXCOORD2,\n"
2840 "#endif\n"
2841 "#ifdef USEREFLECTION\n"
2842 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2843 "#endif\n"
2844 "#ifdef USEFOG\n"
2845 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2846 "#endif\n"
2847 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2848 "out float3 LightVector : TEXCOORD1,\n"
2849 "#endif\n"
2850 "#ifdef MODE_LIGHTSOURCE\n"
2851 "out float3 CubeVector : TEXCOORD3,\n"
2852 "#endif\n"
2853 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2854 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2855 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2856 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2857 "#endif\n"
2858 "#ifdef USESHADOWMAPORTHO\n"
2859 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2860 "#endif\n"
2861 "out float4 gl_Position : POSITION\n"
2862 ")\n"
2863 "{\n"
2864 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2865 "       gl_FrontColor = gl_Color;\n"
2866 "#endif\n"
2867 "       // copy the surface texcoord\n"
2868 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2869 "#ifdef USEVERTEXTEXTUREBLEND\n"
2870 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2871 "#endif\n"
2872 "#ifdef USELIGHTMAP\n"
2873 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2874 "#endif\n"
2875 "\n"
2876 "#ifdef MODE_LIGHTSOURCE\n"
2877 "       // transform vertex position into light attenuation/cubemap space\n"
2878 "       // (-1 to +1 across the light box)\n"
2879 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2880 "\n"
2881 "# ifdef USEDIFFUSE\n"
2882 "       // transform unnormalized light direction into tangent space\n"
2883 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2884 "       //  normalize it per pixel)\n"
2885 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2886 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2887 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2888 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2889 "# endif\n"
2890 "#endif\n"
2891 "\n"
2892 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2893 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2894 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2895 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2896 "#endif\n"
2897 "\n"
2898 "       // transform unnormalized eye direction into tangent space\n"
2899 "#ifdef USEEYEVECTOR\n"
2900 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2901 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2902 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2903 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2904 "#endif\n"
2905 "\n"
2906 "#ifdef USEFOG\n"
2907 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2908 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2909 "#endif\n"
2910 "\n"
2911 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2912 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2913 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2914 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2915 "#endif\n"
2916 "\n"
2917 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2918 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2919 "\n"
2920 "#ifdef USESHADOWMAPORTHO\n"
2921 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2922 "#endif\n"
2923 "\n"
2924 "#ifdef USEREFLECTION\n"
2925 "       ModelViewProjectionPosition = gl_Position;\n"
2926 "#endif\n"
2927 "}\n"
2928 "#endif // VERTEX_SHADER\n"
2929 "\n"
2930 "\n"
2931 "\n"
2932 "\n"
2933 "#ifdef FRAGMENT_SHADER\n"
2934 "void main\n"
2935 "(\n"
2936 "#ifdef USEDEFERREDLIGHTMAP\n"
2937 "#ifdef HLSL\n"
2938 "float2 Pixel : VPOS,\n"
2939 "#else\n"
2940 "float2 Pixel : WPOS,\n"
2941 "#endif\n"
2942 "#endif\n"
2943 "float4 gl_FrontColor : COLOR,\n"
2944 "float4 TexCoordBoth : TEXCOORD0,\n"
2945 "#ifdef USELIGHTMAP\n"
2946 "float2 TexCoordLightmap : TEXCOORD1,\n"
2947 "#endif\n"
2948 "#ifdef USEEYEVECTOR\n"
2949 "float3 EyeVector : TEXCOORD2,\n"
2950 "#endif\n"
2951 "#ifdef USEREFLECTION\n"
2952 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2953 "#endif\n"
2954 "#ifdef USEFOG\n"
2955 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2956 "#endif\n"
2957 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2958 "float3 LightVector : TEXCOORD1,\n"
2959 "#endif\n"
2960 "#ifdef MODE_LIGHTSOURCE\n"
2961 "float3 CubeVector : TEXCOORD3,\n"
2962 "#endif\n"
2963 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2964 "float4 ModelViewPosition : TEXCOORD0,\n"
2965 "#endif\n"
2966 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2967 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2968 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2969 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2970 "#endif\n"
2971 "#ifdef USESHADOWMAPORTHO\n"
2972 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2973 "#endif\n"
2974 "\n"
2975 "uniform sampler Texture_Normal : register(s0),\n"
2976 "uniform sampler Texture_Color : register(s1),\n"
2977 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2978 "uniform sampler Texture_Gloss : register(s2),\n"
2979 "#endif\n"
2980 "#ifdef USEGLOW\n"
2981 "uniform sampler Texture_Glow : register(s3),\n"
2982 "#endif\n"
2983 "#ifdef USEVERTEXTEXTUREBLEND\n"
2984 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2985 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2986 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2987 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2988 "#endif\n"
2989 "#ifdef USEGLOW\n"
2990 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2991 "#endif\n"
2992 "#endif\n"
2993 "#ifdef USECOLORMAPPING\n"
2994 "uniform sampler Texture_Pants : register(s4),\n"
2995 "uniform sampler Texture_Shirt : register(s7),\n"
2996 "#endif\n"
2997 "#ifdef USEFOG\n"
2998 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2999 "uniform sampler Texture_FogMask : register(s8),\n"
3000 "#endif\n"
3001 "#ifdef USELIGHTMAP\n"
3002 "uniform sampler Texture_Lightmap : register(s9),\n"
3003 "#endif\n"
3004 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3005 "uniform sampler Texture_Deluxemap : register(s10),\n"
3006 "#endif\n"
3007 "#ifdef USEREFLECTION\n"
3008 "uniform sampler Texture_Reflection : register(s7),\n"
3009 "#endif\n"
3010 "\n"
3011 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3012 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3013 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3014 "#endif\n"
3015 "#ifdef USEDEFERREDLIGHTMAP\n"
3016 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3017 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3018 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3019 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3020 "#endif\n"
3021 "\n"
3022 "#ifdef USECOLORMAPPING\n"
3023 "uniform half3 Color_Pants : register(c7),\n"
3024 "uniform half3 Color_Shirt : register(c8),\n"
3025 "#endif\n"
3026 "#ifdef USEFOG\n"
3027 "uniform float3 FogColor : register(c16),\n"
3028 "uniform float FogRangeRecip : register(c20),\n"
3029 "uniform float FogPlaneViewDist : register(c19),\n"
3030 "uniform float FogHeightFade : register(c17),\n"
3031 "#endif\n"
3032 "\n"
3033 "#ifdef USEOFFSETMAPPING\n"
3034 "uniform float OffsetMapping_Scale : register(c24),\n"
3035 "#endif\n"
3036 "\n"
3037 "#ifdef USEDEFERREDLIGHTMAP\n"
3038 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3039 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3040 "uniform half3 DeferredMod_Specular : register(c13),\n"
3041 "#endif\n"
3042 "uniform half3 Color_Ambient : register(c3),\n"
3043 "uniform half3 Color_Diffuse : register(c4),\n"
3044 "uniform half3 Color_Specular : register(c5),\n"
3045 "uniform half SpecularPower : register(c36),\n"
3046 "#ifdef USEGLOW\n"
3047 "uniform half3 Color_Glow : register(c6),\n"
3048 "#endif\n"
3049 "uniform half Alpha : register(c0),\n"
3050 "#ifdef USEREFLECTION\n"
3051 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3052 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3053 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3054 "uniform half4 ReflectColor : register(c26),\n"
3055 "#endif\n"
3056 "#ifdef USEREFLECTCUBE\n"
3057 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3058 "uniform sampler Texture_ReflectMask : register(s5),\n"
3059 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3060 "#endif\n"
3061 "#ifdef MODE_LIGHTDIRECTION\n"
3062 "uniform half3 LightColor : register(c21),\n"
3063 "#endif\n"
3064 "#ifdef MODE_LIGHTSOURCE\n"
3065 "uniform half3 LightColor : register(c21),\n"
3066 "#endif\n"
3067 "\n"
3068 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3069 "uniform sampler Texture_Attenuation : register(s9),\n"
3070 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3071 "#endif\n"
3072 "\n"
3073 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3074 "\n"
3075 "#ifdef USESHADOWMAP2D\n"
3076 "# ifdef USESHADOWSAMPLER\n"
3077 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3078 "# else\n"
3079 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3080 "# endif\n"
3081 "#endif\n"
3082 "\n"
3083 "#ifdef USESHADOWMAPVSDCT\n"
3084 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3085 "#endif\n"
3086 "\n"
3087 "#if defined(USESHADOWMAP2D)\n"
3088 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3089 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3090 "#endif\n"
3091 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3092 "\n"
3093 "out float4 gl_FragColor : COLOR\n"
3094 ")\n"
3095 "{\n"
3096 "       float2 TexCoord = TexCoordBoth.xy;\n"
3097 "#ifdef USEVERTEXTEXTUREBLEND\n"
3098 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3099 "#endif\n"
3100 "#ifdef USEOFFSETMAPPING\n"
3101 "       // apply offsetmapping\n"
3102 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3103 "#define TexCoord TexCoordOffset\n"
3104 "#endif\n"
3105 "\n"
3106 "       // combine the diffuse textures (base, pants, shirt)\n"
3107 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3108 "#ifdef USEALPHAKILL\n"
3109 "       if (color.a < 0.5)\n"
3110 "               discard;\n"
3111 "#endif\n"
3112 "       color.a *= Alpha;\n"
3113 "#ifdef USECOLORMAPPING\n"
3114 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3115 "#endif\n"
3116 "#ifdef USEVERTEXTEXTUREBLEND\n"
3117 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3118 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3119 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3120 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3121 "       color.a = 1.0;\n"
3122 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3123 "#endif\n"
3124 "\n"
3125 "       // get the surface normal\n"
3126 "#ifdef USEVERTEXTEXTUREBLEND\n"
3127 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3128 "#else\n"
3129 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3130 "#endif\n"
3131 "\n"
3132 "       // get the material colors\n"
3133 "       half3 diffusetex = color.rgb;\n"
3134 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3135 "# ifdef USEVERTEXTEXTUREBLEND\n"
3136 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3137 "# else\n"
3138 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3139 "# endif\n"
3140 "#endif\n"
3141 "\n"
3142 "#ifdef USEREFLECTCUBE\n"
3143 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3144 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3145 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3146 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3147 "#endif\n"
3148 "\n"
3149 "\n"
3150 "\n"
3151 "\n"
3152 "#ifdef MODE_LIGHTSOURCE\n"
3153 "       // light source\n"
3154 "#ifdef USEDIFFUSE\n"
3155 "       half3 lightnormal = half3(normalize(LightVector));\n"
3156 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3157 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3158 "#ifdef USESPECULAR\n"
3159 "#ifdef USEEXACTSPECULARMATH\n"
3160 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3161 "#else\n"
3162 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3163 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3164 "#endif\n"
3165 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3166 "#endif\n"
3167 "#else\n"
3168 "       color.rgb = diffusetex * Color_Ambient;\n"
3169 "#endif\n"
3170 "       color.rgb *= LightColor;\n"
3171 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3172 "#if defined(USESHADOWMAP2D)\n"
3173 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3174 "#ifdef USESHADOWMAPVSDCT\n"
3175 ", Texture_CubeProjection\n"
3176 "#endif\n"
3177 "       ));\n"
3178 "\n"
3179 "#endif\n"
3180 "# ifdef USECUBEFILTER\n"
3181 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3182 "# endif\n"
3183 "\n"
3184 "#ifdef USESHADOWMAP2D\n"
3185 "#ifdef USESHADOWMAPVSDCT\n"
3186 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3187 "#else\n"
3188 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3189 "#endif\n"
3190 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3191 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3192 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3193 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3194 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3195 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3196 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3197 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3198 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3199 "//     color.r = half(shadowmaptc.z);\n"
3200 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3201 "//     color.r = half(shadowmaptc.z);\n"
3202 "//     color.r = 1;\n"
3203 "//     color.rgb = abs(CubeVector);\n"
3204 "#endif\n"
3205 "//     color.rgb = half3(1,1,1);\n"
3206 "#endif // MODE_LIGHTSOURCE\n"
3207 "\n"
3208 "\n"
3209 "\n"
3210 "\n"
3211 "#ifdef MODE_LIGHTDIRECTION\n"
3212 "#define SHADING\n"
3213 "#ifdef USEDIFFUSE\n"
3214 "       half3 lightnormal = half3(normalize(LightVector));\n"
3215 "#endif\n"
3216 "#define lightcolor LightColor\n"
3217 "#endif // MODE_LIGHTDIRECTION\n"
3218 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3219 "#define SHADING\n"
3220 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3221 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3222 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3223 "       // convert modelspace light vector to tangentspace\n"
3224 "       half3 lightnormal;\n"
3225 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3226 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3227 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3228 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3229 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3230 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3231 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3232 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3233 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3234 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3235 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3236 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3237 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3238 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3239 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3240 "#define SHADING\n"
3241 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3242 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3243 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3244 "#endif\n"
3245 "\n"
3246 "\n"
3247 "\n"
3248 "\n"
3249 "#ifdef MODE_FAKELIGHT\n"
3250 "#define SHADING\n"
3251 "half3 lightnormal = half3(normalize(EyeVector));\n"
3252 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3253 "#endif // MODE_FAKELIGHT\n"
3254 "\n"
3255 "\n"
3256 "\n"
3257 "\n"
3258 "#ifdef MODE_LIGHTMAP\n"
3259 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3260 "#endif // MODE_LIGHTMAP\n"
3261 "#ifdef MODE_VERTEXCOLOR\n"
3262 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3263 "#endif // MODE_VERTEXCOLOR\n"
3264 "#ifdef MODE_FLATCOLOR\n"
3265 "       color.rgb = diffusetex * Color_Ambient;\n"
3266 "#endif // MODE_FLATCOLOR\n"
3267 "\n"
3268 "\n"
3269 "\n"
3270 "\n"
3271 "#ifdef SHADING\n"
3272 "# ifdef USEDIFFUSE\n"
3273 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3274 "#  ifdef USESPECULAR\n"
3275 "#   ifdef USEEXACTSPECULARMATH\n"
3276 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3277 "#   else\n"
3278 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3279 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3280 "#   endif\n"
3281 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3282 "#  else\n"
3283 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3284 "#  endif\n"
3285 "# else\n"
3286 "       color.rgb = diffusetex * Color_Ambient;\n"
3287 "# endif\n"
3288 "#endif\n"
3289 "\n"
3290 "#ifdef USESHADOWMAPORTHO\n"
3291 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3292 "#endif\n"
3293 "\n"
3294 "#ifdef USEDEFERREDLIGHTMAP\n"
3295 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3296 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3297 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3298 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3299 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3300 "#endif\n"
3301 "\n"
3302 "#ifdef USEGLOW\n"
3303 "#ifdef USEVERTEXTEXTUREBLEND\n"
3304 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3305 "#else\n"
3306 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3307 "#endif\n"
3308 "#endif\n"
3309 "\n"
3310 "#ifdef USEFOG\n"
3311 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3312 "#endif\n"
3313 "\n"
3314 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3315 "#ifdef USEREFLECTION\n"
3316 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3317 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3318 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3319 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3320 "       // FIXME temporary hack to detect the case that the reflection\n"
3321 "       // gets blackened at edges due to leaving the area that contains actual\n"
3322 "       // content.\n"
3323 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3324 "       // 'appening.\n"
3325 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3326 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3327 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3328 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3329 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3330 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3331 "#endif\n"
3332 "\n"
3333 "       gl_FragColor = float4(color);\n"
3334 "}\n"
3335 "#endif // FRAGMENT_SHADER\n"
3336 "\n"
3337 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3338 "#endif // !MODE_DEFERREDGEOMETRY\n"
3339 "#endif // !MODE_WATER\n"
3340 "#endif // !MODE_REFRACTION\n"
3341 "#endif // !MODE_BLOOMBLUR\n"
3342 "#endif // !MODE_GENERIC\n"
3343 "#endif // !MODE_POSTPROCESS\n"
3344 "#endif // !MODE_SHOWDEPTH\n"
3345 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3346 ;
3347
3348 char *glslshaderstring = NULL;
3349 char *hlslshaderstring = NULL;
3350
3351 //=======================================================================================================================================================
3352
3353 typedef struct shaderpermutationinfo_s
3354 {
3355         const char *pretext;
3356         const char *name;
3357 }
3358 shaderpermutationinfo_t;
3359
3360 typedef struct shadermodeinfo_s
3361 {
3362         const char *vertexfilename;
3363         const char *geometryfilename;
3364         const char *fragmentfilename;
3365         const char *pretext;
3366         const char *name;
3367 }
3368 shadermodeinfo_t;
3369
3370 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3371 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3372 {
3373         {"#define USEDIFFUSE\n", " diffuse"},
3374         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3375         {"#define USEVIEWTINT\n", " viewtint"},
3376         {"#define USECOLORMAPPING\n", " colormapping"},
3377         {"#define USESATURATION\n", " saturation"},
3378         {"#define USEFOGINSIDE\n", " foginside"},
3379         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3380         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3381         {"#define USEGAMMARAMPS\n", " gammaramps"},
3382         {"#define USECUBEFILTER\n", " cubefilter"},
3383         {"#define USEGLOW\n", " glow"},
3384         {"#define USEBLOOM\n", " bloom"},
3385         {"#define USESPECULAR\n", " specular"},
3386         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3387         {"#define USEREFLECTION\n", " reflection"},
3388         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3389         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3390         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3391         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3392         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3393         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3394         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3395         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3396         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3397         {"#define USEALPHAKILL\n", " alphakill"},
3398         {"#define USEREFLECTCUBE\n", " reflectcube"},
3399         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3400         {"#define USEBOUNCEGRID\n", " bouncegrid"},
3401 };
3402
3403 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3404 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3405 {
3406         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3407         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3408         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3409         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3410         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3411         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3412         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3413         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3414         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3415         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3416         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3417         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3418         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3419         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3420         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3421         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3422 };
3423
3424 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3425 {
3426         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3427         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3428         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3429         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3430         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3431         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3432         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3433         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3434         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3435         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3436         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3437         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3438         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3439         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3440         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3441         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3442 };
3443
3444 struct r_glsl_permutation_s;
3445 typedef struct r_glsl_permutation_s
3446 {
3447         /// hash lookup data
3448         struct r_glsl_permutation_s *hashnext;
3449         unsigned int mode;
3450         unsigned int permutation;
3451
3452         /// indicates if we have tried compiling this permutation already
3453         qboolean compiled;
3454         /// 0 if compilation failed
3455         int program;
3456         // texture units assigned to each detected uniform
3457         int tex_Texture_First;
3458         int tex_Texture_Second;
3459         int tex_Texture_GammaRamps;
3460         int tex_Texture_Normal;
3461         int tex_Texture_Color;
3462         int tex_Texture_Gloss;
3463         int tex_Texture_Glow;
3464         int tex_Texture_SecondaryNormal;
3465         int tex_Texture_SecondaryColor;
3466         int tex_Texture_SecondaryGloss;
3467         int tex_Texture_SecondaryGlow;
3468         int tex_Texture_Pants;
3469         int tex_Texture_Shirt;
3470         int tex_Texture_FogHeightTexture;
3471         int tex_Texture_FogMask;
3472         int tex_Texture_Lightmap;
3473         int tex_Texture_Deluxemap;
3474         int tex_Texture_Attenuation;
3475         int tex_Texture_Cube;
3476         int tex_Texture_Refraction;
3477         int tex_Texture_Reflection;
3478         int tex_Texture_ShadowMap2D;
3479         int tex_Texture_CubeProjection;
3480         int tex_Texture_ScreenDepth;
3481         int tex_Texture_ScreenNormalMap;
3482         int tex_Texture_ScreenDiffuse;
3483         int tex_Texture_ScreenSpecular;
3484         int tex_Texture_ReflectMask;
3485         int tex_Texture_ReflectCube;
3486         int tex_Texture_BounceGrid;
3487         /// locations of detected uniforms in program object, or -1 if not found
3488         int loc_Texture_First;
3489         int loc_Texture_Second;
3490         int loc_Texture_GammaRamps;
3491         int loc_Texture_Normal;
3492         int loc_Texture_Color;
3493         int loc_Texture_Gloss;
3494         int loc_Texture_Glow;
3495         int loc_Texture_SecondaryNormal;
3496         int loc_Texture_SecondaryColor;
3497         int loc_Texture_SecondaryGloss;
3498         int loc_Texture_SecondaryGlow;
3499         int loc_Texture_Pants;
3500         int loc_Texture_Shirt;
3501         int loc_Texture_FogHeightTexture;
3502         int loc_Texture_FogMask;
3503         int loc_Texture_Lightmap;
3504         int loc_Texture_Deluxemap;
3505         int loc_Texture_Attenuation;
3506         int loc_Texture_Cube;
3507         int loc_Texture_Refraction;
3508         int loc_Texture_Reflection;
3509         int loc_Texture_ShadowMap2D;
3510         int loc_Texture_CubeProjection;
3511         int loc_Texture_ScreenDepth;
3512         int loc_Texture_ScreenNormalMap;
3513         int loc_Texture_ScreenDiffuse;
3514         int loc_Texture_ScreenSpecular;
3515         int loc_Texture_ReflectMask;
3516         int loc_Texture_ReflectCube;
3517         int loc_Texture_BounceGrid;
3518         int loc_Alpha;
3519         int loc_BloomBlur_Parameters;
3520         int loc_ClientTime;
3521         int loc_Color_Ambient;
3522         int loc_Color_Diffuse;
3523         int loc_Color_Specular;
3524         int loc_Color_Glow;
3525         int loc_Color_Pants;
3526         int loc_Color_Shirt;
3527         int loc_DeferredColor_Ambient;
3528         int loc_DeferredColor_Diffuse;
3529         int loc_DeferredColor_Specular;
3530         int loc_DeferredMod_Diffuse;
3531         int loc_DeferredMod_Specular;
3532         int loc_DistortScaleRefractReflect;
3533         int loc_EyePosition;
3534         int loc_FogColor;
3535         int loc_FogHeightFade;
3536         int loc_FogPlane;
3537         int loc_FogPlaneViewDist;
3538         int loc_FogRangeRecip;
3539         int loc_LightColor;
3540         int loc_LightDir;
3541         int loc_LightPosition;
3542         int loc_OffsetMapping_Scale;
3543         int loc_PixelSize;
3544         int loc_ReflectColor;
3545         int loc_ReflectFactor;
3546         int loc_ReflectOffset;
3547         int loc_RefractColor;
3548         int loc_Saturation;
3549         int loc_ScreenCenterRefractReflect;
3550         int loc_ScreenScaleRefractReflect;
3551         int loc_ScreenToDepth;
3552         int loc_ShadowMap_Parameters;
3553         int loc_ShadowMap_TextureScale;
3554         int loc_SpecularPower;
3555         int loc_UserVec1;
3556         int loc_UserVec2;
3557         int loc_UserVec3;
3558         int loc_UserVec4;
3559         int loc_ViewTintColor;
3560         int loc_ViewToLight;
3561         int loc_ModelToLight;
3562         int loc_TexMatrix;
3563         int loc_BackgroundTexMatrix;
3564         int loc_ModelViewProjectionMatrix;
3565         int loc_ModelViewMatrix;
3566         int loc_PixelToScreenTexCoord;
3567         int loc_ModelToReflectCube;
3568         int loc_ShadowMapMatrix;
3569         int loc_BloomColorSubtract;
3570         int loc_NormalmapScrollBlend;
3571         int loc_BounceGridMatrix;
3572         int loc_BounceGridIntensity;
3573 }
3574 r_glsl_permutation_t;
3575
3576 #define SHADERPERMUTATION_HASHSIZE 256
3577
3578
3579 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3580 // these can NOT degrade! only use for simple stuff
3581 enum
3582 {
3583         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3584         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3585         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3586         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3587         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3588         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3589 };
3590 #define SHADERSTATICPARMS_COUNT 6
3591
3592 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3593 static int shaderstaticparms_count = 0;
3594
3595 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3596 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3597 qboolean R_CompileShader_CheckStaticParms(void)
3598 {
3599         static int r_compileshader_staticparms_save[1];
3600         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3601         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3602
3603         // detect all
3604         if (r_glsl_saturation_redcompensate.integer)
3605                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3606         if (r_shadow_glossexact.integer)
3607                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3608         if (r_glsl_postprocess.integer)
3609         {
3610                 if (r_glsl_postprocess_uservec1_enable.integer)
3611                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3612                 if (r_glsl_postprocess_uservec2_enable.integer)
3613                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3614                 if (r_glsl_postprocess_uservec3_enable.integer)
3615                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3616                 if (r_glsl_postprocess_uservec4_enable.integer)
3617                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3618         }
3619         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3620 }
3621
3622 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3623         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3624                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3625         else \
3626                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3627 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3628 {
3629         shaderstaticparms_count = 0;
3630
3631         // emit all
3632         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3633         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3634         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3635         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3636         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3637         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3638 }
3639
3640 /// information about each possible shader permutation
3641 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3642 /// currently selected permutation
3643 r_glsl_permutation_t *r_glsl_permutation;
3644 /// storage for permutations linked in the hash table
3645 memexpandablearray_t r_glsl_permutationarray;
3646
3647 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3648 {
3649         //unsigned int hashdepth = 0;
3650         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3651         r_glsl_permutation_t *p;
3652         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3653         {
3654                 if (p->mode == mode && p->permutation == permutation)
3655                 {
3656                         //if (hashdepth > 10)
3657                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3658                         return p;
3659                 }
3660                 //hashdepth++;
3661         }
3662         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3663         p->mode = mode;
3664         p->permutation = permutation;
3665         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3666         r_glsl_permutationhash[mode][hashindex] = p;
3667         //if (hashdepth > 10)
3668         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3669         return p;
3670 }
3671
3672 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3673 {
3674         char *shaderstring;
3675         if (!filename || !filename[0])
3676                 return NULL;
3677         if (!strcmp(filename, "glsl/default.glsl"))
3678         {
3679                 if (!glslshaderstring)
3680                 {
3681                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3682                         if (glslshaderstring)
3683                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3684                         else
3685                                 glslshaderstring = (char *)builtinshaderstring;
3686                 }
3687                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3688                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3689                 return shaderstring;
3690         }
3691         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3692         if (shaderstring)
3693         {
3694                 if (printfromdisknotice)
3695                         Con_DPrintf("from disk %s... ", filename);
3696                 return shaderstring;
3697         }
3698         return shaderstring;
3699 }
3700
3701 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3702 {
3703         int i;
3704         int sampler;
3705         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3706         char *vertexstring, *geometrystring, *fragmentstring;
3707         char permutationname[256];
3708         int vertstrings_count = 0;
3709         int geomstrings_count = 0;
3710         int fragstrings_count = 0;
3711         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3712         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3713         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3714
3715         if (p->compiled)
3716                 return;
3717         p->compiled = true;
3718         p->program = 0;
3719
3720         permutationname[0] = 0;
3721         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3722         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3723         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3724
3725         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3726
3727         // the first pretext is which type of shader to compile as
3728         // (later these will all be bound together as a program object)
3729         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3730         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3731         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3732
3733         // the second pretext is the mode (for example a light source)
3734         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3735         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3736         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3737         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3738
3739         // now add all the permutation pretexts
3740         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3741         {
3742                 if (permutation & (1<<i))
3743                 {
3744                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3745                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3746                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3747                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3748                 }
3749                 else
3750                 {
3751                         // keep line numbers correct
3752                         vertstrings_list[vertstrings_count++] = "\n";
3753                         geomstrings_list[geomstrings_count++] = "\n";
3754                         fragstrings_list[fragstrings_count++] = "\n";
3755                 }
3756         }
3757
3758         // add static parms
3759         R_CompileShader_AddStaticParms(mode, permutation);
3760         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3761         vertstrings_count += shaderstaticparms_count;
3762         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3763         geomstrings_count += shaderstaticparms_count;
3764         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3765         fragstrings_count += shaderstaticparms_count;
3766
3767         // now append the shader text itself
3768         vertstrings_list[vertstrings_count++] = vertexstring;
3769         geomstrings_list[geomstrings_count++] = geometrystring;
3770         fragstrings_list[fragstrings_count++] = fragmentstring;
3771
3772         // if any sources were NULL, clear the respective list
3773         if (!vertexstring)
3774                 vertstrings_count = 0;
3775         if (!geometrystring)
3776                 geomstrings_count = 0;
3777         if (!fragmentstring)
3778                 fragstrings_count = 0;
3779
3780         // compile the shader program
3781         if (vertstrings_count + geomstrings_count + fragstrings_count)
3782                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3783         if (p->program)
3784         {
3785                 CHECKGLERROR
3786                 qglUseProgram(p->program);CHECKGLERROR
3787                 // look up all the uniform variable names we care about, so we don't
3788                 // have to look them up every time we set them
3789
3790                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
3791                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
3792                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3793                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
3794                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
3795                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
3796                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
3797                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3798                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3799                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3800                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3801                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
3802                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
3803                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3804                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
3805                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
3806                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3807                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
3808                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
3809                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
3810                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
3811                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3812                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3813                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3814                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3815                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3816                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3817                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3818                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3819                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
3820                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
3821                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3822                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
3823                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
3824                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
3825                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
3826                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
3827                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
3828                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
3829                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3830                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3831                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3832                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3833                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3834                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3835                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
3836                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
3837                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
3838                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
3839                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3840                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
3841                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
3842                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
3843                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
3844                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3845                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
3846                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
3847                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
3848                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
3849                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
3850                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
3851                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3852                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3853                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
3854                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3855                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3856                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
3857                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
3858                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
3859                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
3860                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
3861                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
3862                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
3863                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
3864                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
3865                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3866                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
3867                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3868                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3869                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
3870                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3871                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
3872                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3873                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
3874                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
3875                 // initialize the samplers to refer to the texture units we use
3876                 p->tex_Texture_First = -1;
3877                 p->tex_Texture_Second = -1;
3878                 p->tex_Texture_GammaRamps = -1;
3879                 p->tex_Texture_Normal = -1;
3880                 p->tex_Texture_Color = -1;
3881                 p->tex_Texture_Gloss = -1;
3882                 p->tex_Texture_Glow = -1;
3883                 p->tex_Texture_SecondaryNormal = -1;
3884                 p->tex_Texture_SecondaryColor = -1;
3885                 p->tex_Texture_SecondaryGloss = -1;
3886                 p->tex_Texture_SecondaryGlow = -1;
3887                 p->tex_Texture_Pants = -1;
3888                 p->tex_Texture_Shirt = -1;
3889                 p->tex_Texture_FogHeightTexture = -1;
3890                 p->tex_Texture_FogMask = -1;
3891                 p->tex_Texture_Lightmap = -1;
3892                 p->tex_Texture_Deluxemap = -1;
3893                 p->tex_Texture_Attenuation = -1;
3894                 p->tex_Texture_Cube = -1;
3895                 p->tex_Texture_Refraction = -1;
3896                 p->tex_Texture_Reflection = -1;
3897                 p->tex_Texture_ShadowMap2D = -1;
3898                 p->tex_Texture_CubeProjection = -1;
3899                 p->tex_Texture_ScreenDepth = -1;
3900                 p->tex_Texture_ScreenNormalMap = -1;
3901                 p->tex_Texture_ScreenDiffuse = -1;
3902                 p->tex_Texture_ScreenSpecular = -1;
3903                 p->tex_Texture_ReflectMask = -1;
3904                 p->tex_Texture_ReflectCube = -1;
3905                 p->tex_Texture_BounceGrid = -1;
3906                 sampler = 0;
3907                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
3908                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
3909                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
3910                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
3911                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
3912                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
3913                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
3914                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3915                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
3916                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
3917                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
3918                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
3919                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
3920                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3921                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
3922                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
3923                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
3924                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
3925                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
3926                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
3927                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
3928                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
3929                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
3930                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
3931                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3932                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
3933                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
3934                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
3935                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
3936                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
3937                 CHECKGLERROR
3938                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3939         }
3940         else
3941                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3942
3943         // free the strings
3944         if (vertexstring)
3945                 Mem_Free(vertexstring);
3946         if (geometrystring)
3947                 Mem_Free(geometrystring);
3948         if (fragmentstring)
3949                 Mem_Free(fragmentstring);
3950 }
3951
3952 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3953 {
3954         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3955         if (r_glsl_permutation != perm)
3956         {
3957                 r_glsl_permutation = perm;
3958                 if (!r_glsl_permutation->program)
3959                 {
3960                         if (!r_glsl_permutation->compiled)
3961                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3962                         if (!r_glsl_permutation->program)
3963                         {
3964                                 // remove features until we find a valid permutation
3965                                 int i;
3966                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3967                                 {
3968                                         // reduce i more quickly whenever it would not remove any bits
3969                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3970                                         if (!(permutation & j))
3971                                                 continue;
3972                                         permutation -= j;
3973                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3974                                         if (!r_glsl_permutation->compiled)
3975                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3976                                         if (r_glsl_permutation->program)
3977                                                 break;
3978                                 }
3979                                 if (i >= SHADERPERMUTATION_COUNT)
3980                                 {
3981                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3982                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3983                                         qglUseProgram(0);CHECKGLERROR
3984                                         return; // no bit left to clear, entire mode is broken
3985                                 }
3986                         }
3987                 }
3988                 CHECKGLERROR
3989                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
3990         }
3991         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3992         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3993         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
3994 }
3995
3996 #ifdef SUPPORTD3D
3997
3998 #ifdef SUPPORTD3D
3999 #include <d3d9.h>
4000 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4001 extern D3DCAPS9 vid_d3d9caps;
4002 #endif
4003
4004 struct r_hlsl_permutation_s;
4005 typedef struct r_hlsl_permutation_s
4006 {
4007         /// hash lookup data
4008         struct r_hlsl_permutation_s *hashnext;
4009         unsigned int mode;
4010         unsigned int permutation;
4011
4012         /// indicates if we have tried compiling this permutation already
4013         qboolean compiled;
4014         /// NULL if compilation failed
4015         IDirect3DVertexShader9 *vertexshader;
4016         IDirect3DPixelShader9 *pixelshader;
4017 }
4018 r_hlsl_permutation_t;
4019
4020 typedef enum D3DVSREGISTER_e
4021 {
4022         D3DVSREGISTER_TexMatrix = 0, // float4x4
4023         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4024         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4025         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4026         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4027         D3DVSREGISTER_ModelToLight = 20, // float4x4
4028         D3DVSREGISTER_EyePosition = 24,
4029         D3DVSREGISTER_FogPlane = 25,
4030         D3DVSREGISTER_LightDir = 26,
4031         D3DVSREGISTER_LightPosition = 27,
4032 }
4033 D3DVSREGISTER_t;
4034
4035 typedef enum D3DPSREGISTER_e
4036 {
4037         D3DPSREGISTER_Alpha = 0,
4038         D3DPSREGISTER_BloomBlur_Parameters = 1,
4039         D3DPSREGISTER_ClientTime = 2,
4040         D3DPSREGISTER_Color_Ambient = 3,
4041         D3DPSREGISTER_Color_Diffuse = 4,
4042         D3DPSREGISTER_Color_Specular = 5,
4043         D3DPSREGISTER_Color_Glow = 6,
4044         D3DPSREGISTER_Color_Pants = 7,
4045         D3DPSREGISTER_Color_Shirt = 8,
4046         D3DPSREGISTER_DeferredColor_Ambient = 9,
4047         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4048         D3DPSREGISTER_DeferredColor_Specular = 11,
4049         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4050         D3DPSREGISTER_DeferredMod_Specular = 13,
4051         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4052         D3DPSREGISTER_EyePosition = 15, // unused
4053         D3DPSREGISTER_FogColor = 16,
4054         D3DPSREGISTER_FogHeightFade = 17,
4055         D3DPSREGISTER_FogPlane = 18,
4056         D3DPSREGISTER_FogPlaneViewDist = 19,
4057         D3DPSREGISTER_FogRangeRecip = 20,
4058         D3DPSREGISTER_LightColor = 21,
4059         D3DPSREGISTER_LightDir = 22, // unused
4060         D3DPSREGISTER_LightPosition = 23,
4061         D3DPSREGISTER_OffsetMapping_Scale = 24,
4062         D3DPSREGISTER_PixelSize = 25,
4063         D3DPSREGISTER_ReflectColor = 26,
4064         D3DPSREGISTER_ReflectFactor = 27,
4065         D3DPSREGISTER_ReflectOffset = 28,
4066         D3DPSREGISTER_RefractColor = 29,
4067         D3DPSREGISTER_Saturation = 30,
4068         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4069         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4070         D3DPSREGISTER_ScreenToDepth = 33,
4071         D3DPSREGISTER_ShadowMap_Parameters = 34,
4072         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4073         D3DPSREGISTER_SpecularPower = 36,
4074         D3DPSREGISTER_UserVec1 = 37,
4075         D3DPSREGISTER_UserVec2 = 38,
4076         D3DPSREGISTER_UserVec3 = 39,
4077         D3DPSREGISTER_UserVec4 = 40,
4078         D3DPSREGISTER_ViewTintColor = 41,
4079         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4080         D3DPSREGISTER_BloomColorSubtract = 43,
4081         D3DPSREGISTER_ViewToLight = 44, // float4x4
4082         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4083         D3DPSREGISTER_NormalmapScrollBlend = 52,
4084         // next at 53
4085 }
4086 D3DPSREGISTER_t;
4087
4088 /// information about each possible shader permutation
4089 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4090 /// currently selected permutation
4091 r_hlsl_permutation_t *r_hlsl_permutation;
4092 /// storage for permutations linked in the hash table
4093 memexpandablearray_t r_hlsl_permutationarray;
4094
4095 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4096 {
4097         //unsigned int hashdepth = 0;
4098         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4099         r_hlsl_permutation_t *p;
4100         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4101         {
4102                 if (p->mode == mode && p->permutation == permutation)
4103                 {
4104                         //if (hashdepth > 10)
4105                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4106                         return p;
4107                 }
4108                 //hashdepth++;
4109         }
4110         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4111         p->mode = mode;
4112         p->permutation = permutation;
4113         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4114         r_hlsl_permutationhash[mode][hashindex] = p;
4115         //if (hashdepth > 10)
4116         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4117         return p;
4118 }
4119
4120 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4121 {
4122         char *shaderstring;
4123         if (!filename || !filename[0])
4124                 return NULL;
4125         if (!strcmp(filename, "hlsl/default.hlsl"))
4126         {
4127                 if (!hlslshaderstring)
4128                 {
4129                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4130                         if (hlslshaderstring)
4131                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4132                         else
4133                                 hlslshaderstring = (char *)builtinhlslshaderstring;
4134                 }
4135                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4136                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4137                 return shaderstring;
4138         }
4139         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4140         if (shaderstring)
4141         {
4142                 if (printfromdisknotice)
4143                         Con_DPrintf("from disk %s... ", filename);
4144                 return shaderstring;
4145         }
4146         return shaderstring;
4147 }
4148
4149 #include <d3dx9.h>
4150 //#include <d3dx9shader.h>
4151 //#include <d3dx9mesh.h>
4152
4153 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4154 {
4155         DWORD *vsbin = NULL;
4156         DWORD *psbin = NULL;
4157         fs_offset_t vsbinsize;
4158         fs_offset_t psbinsize;
4159 //      IDirect3DVertexShader9 *vs = NULL;
4160 //      IDirect3DPixelShader9 *ps = NULL;
4161         ID3DXBuffer *vslog = NULL;
4162         ID3DXBuffer *vsbuffer = NULL;
4163         ID3DXConstantTable *vsconstanttable = NULL;
4164         ID3DXBuffer *pslog = NULL;
4165         ID3DXBuffer *psbuffer = NULL;
4166         ID3DXConstantTable *psconstanttable = NULL;
4167         int vsresult = 0;
4168         int psresult = 0;
4169         char temp[MAX_INPUTLINE];
4170         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4171         qboolean debugshader = gl_paranoid.integer != 0;
4172         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4173         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4174         if (!debugshader)
4175         {
4176                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4177                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4178         }
4179         if ((!vsbin && vertstring) || (!psbin && fragstring))
4180         {
4181                 const char* dllnames_d3dx9 [] =
4182                 {
4183                         "d3dx9_43.dll",
4184                         "d3dx9_42.dll",
4185                         "d3dx9_41.dll",
4186                         "d3dx9_40.dll",
4187                         "d3dx9_39.dll",
4188                         "d3dx9_38.dll",
4189                         "d3dx9_37.dll",
4190                         "d3dx9_36.dll",
4191                         "d3dx9_35.dll",
4192                         "d3dx9_34.dll",
4193                         "d3dx9_33.dll",
4194                         "d3dx9_32.dll",
4195                         "d3dx9_31.dll",
4196                         "d3dx9_30.dll",
4197                         "d3dx9_29.dll",
4198                         "d3dx9_28.dll",
4199                         "d3dx9_27.dll",
4200                         "d3dx9_26.dll",
4201                         "d3dx9_25.dll",
4202                         "d3dx9_24.dll",
4203                         NULL
4204                 };
4205                 dllhandle_t d3dx9_dll = NULL;
4206                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4207                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4208                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4209                 dllfunction_t d3dx9_dllfuncs[] =
4210                 {
4211                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4212                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4213                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4214                         {NULL, NULL}
4215                 };
4216                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4217                 {
4218                         DWORD shaderflags = 0;
4219                         if (debugshader)
4220                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4221                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4222                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4223                         if (vertstring && vertstring[0])
4224                         {
4225                                 if (debugshader)
4226                                 {
4227 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4228 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4229                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4230                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4231                                 }
4232                                 else
4233                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4234                                 if (vsbuffer)
4235                                 {
4236                                         vsbinsize = vsbuffer->GetBufferSize();
4237                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4238                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4239                                         vsbuffer->Release();
4240                                 }
4241                                 if (vslog)
4242                                 {
4243                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4244                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4245                                         vslog->Release();
4246                                 }
4247                         }
4248                         if (fragstring && fragstring[0])
4249                         {
4250                                 if (debugshader)
4251                                 {
4252 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4253 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4254                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4255                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4256                                 }
4257                                 else
4258                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4259                                 if (psbuffer)
4260                                 {
4261                                         psbinsize = psbuffer->GetBufferSize();
4262                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4263                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4264                                         psbuffer->Release();
4265                                 }
4266                                 if (pslog)
4267                                 {
4268                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4269                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4270                                         pslog->Release();
4271                                 }
4272                         }
4273                         Sys_UnloadLibrary(&d3dx9_dll);
4274                 }
4275                 else
4276                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4277         }
4278         if (vsbin && psbin)
4279         {
4280                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4281                 if (FAILED(vsresult))
4282                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4283                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4284                 if (FAILED(psresult))
4285                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4286         }
4287         // free the shader data
4288         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4289         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4290 }
4291
4292 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4293 {
4294         int i;
4295         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4296         int vertstring_length = 0;
4297         int geomstring_length = 0;
4298         int fragstring_length = 0;
4299         char *t;
4300         char *vertexstring, *geometrystring, *fragmentstring;
4301         char *vertstring, *geomstring, *fragstring;
4302         char permutationname[256];
4303         char cachename[256];
4304         int vertstrings_count = 0;
4305         int geomstrings_count = 0;
4306         int fragstrings_count = 0;
4307         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4308         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4309         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4310
4311         if (p->compiled)
4312                 return;
4313         p->compiled = true;
4314         p->vertexshader = NULL;
4315         p->pixelshader = NULL;
4316
4317         permutationname[0] = 0;
4318         cachename[0] = 0;
4319         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4320         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4321         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4322
4323         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4324         strlcat(cachename, "hlsl/", sizeof(cachename));
4325
4326         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4327         vertstrings_count = 0;
4328         geomstrings_count = 0;
4329         fragstrings_count = 0;
4330         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4331         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4332         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4333
4334         // the first pretext is which type of shader to compile as
4335         // (later these will all be bound together as a program object)
4336         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4337         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4338         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4339
4340         // the second pretext is the mode (for example a light source)
4341         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4342         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4343         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4344         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4345         strlcat(cachename, modeinfo->name, sizeof(cachename));
4346
4347         // now add all the permutation pretexts
4348         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4349         {
4350                 if (permutation & (1<<i))
4351                 {
4352                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4353                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4354                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4355                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4356                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4357                 }
4358                 else
4359                 {
4360                         // keep line numbers correct
4361                         vertstrings_list[vertstrings_count++] = "\n";
4362                         geomstrings_list[geomstrings_count++] = "\n";
4363                         fragstrings_list[fragstrings_count++] = "\n";
4364                 }
4365         }
4366
4367         // add static parms
4368         R_CompileShader_AddStaticParms(mode, permutation);
4369         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4370         vertstrings_count += shaderstaticparms_count;
4371         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4372         geomstrings_count += shaderstaticparms_count;
4373         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4374         fragstrings_count += shaderstaticparms_count;
4375
4376         // replace spaces in the cachename with _ characters
4377         for (i = 0;cachename[i];i++)
4378                 if (cachename[i] == ' ')
4379                         cachename[i] = '_';
4380
4381         // now append the shader text itself
4382         vertstrings_list[vertstrings_count++] = vertexstring;
4383         geomstrings_list[geomstrings_count++] = geometrystring;
4384         fragstrings_list[fragstrings_count++] = fragmentstring;
4385
4386         // if any sources were NULL, clear the respective list
4387         if (!vertexstring)
4388                 vertstrings_count = 0;
4389         if (!geometrystring)
4390                 geomstrings_count = 0;
4391         if (!fragmentstring)
4392                 fragstrings_count = 0;
4393
4394         vertstring_length = 0;
4395         for (i = 0;i < vertstrings_count;i++)
4396                 vertstring_length += strlen(vertstrings_list[i]);
4397         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4398         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4399                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4400
4401         geomstring_length = 0;
4402         for (i = 0;i < geomstrings_count;i++)
4403                 geomstring_length += strlen(geomstrings_list[i]);
4404         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4405         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4406                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4407
4408         fragstring_length = 0;
4409         for (i = 0;i < fragstrings_count;i++)
4410                 fragstring_length += strlen(fragstrings_list[i]);
4411         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4412         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4413                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4414
4415         // try to load the cached shader, or generate one
4416         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4417
4418         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4419                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4420         else
4421                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4422
4423         // free the strings
4424         if (vertstring)
4425                 Mem_Free(vertstring);
4426         if (geomstring)
4427                 Mem_Free(geomstring);
4428         if (fragstring)
4429                 Mem_Free(fragstring);
4430         if (vertexstring)
4431                 Mem_Free(vertexstring);
4432         if (geometrystring)
4433                 Mem_Free(geometrystring);
4434         if (fragmentstring)
4435                 Mem_Free(fragmentstring);
4436 }
4437
4438 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4439 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4440 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);}
4441 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);}
4442 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);}
4443 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);}
4444
4445 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4446 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4447 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);}
4448 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);}
4449 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);}
4450 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);}
4451
4452 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4453 {
4454         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4455         if (r_hlsl_permutation != perm)
4456         {
4457                 r_hlsl_permutation = perm;
4458                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4459                 {
4460                         if (!r_hlsl_permutation->compiled)
4461                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4462                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4463                         {
4464                                 // remove features until we find a valid permutation
4465                                 int i;
4466                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4467                                 {
4468                                         // reduce i more quickly whenever it would not remove any bits
4469                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4470                                         if (!(permutation & j))
4471                                                 continue;
4472                                         permutation -= j;
4473                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4474                                         if (!r_hlsl_permutation->compiled)
4475                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4476                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4477                                                 break;
4478                                 }
4479                                 if (i >= SHADERPERMUTATION_COUNT)
4480                                 {
4481                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4482                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4483                                         return; // no bit left to clear, entire mode is broken
4484                                 }
4485                         }
4486                 }
4487                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4488                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4489         }
4490         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4491         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4492         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4493 }
4494 #endif
4495
4496 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4497 {
4498         DPSOFTRAST_SetShader(mode, permutation);
4499         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4500         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4501         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4502 }
4503
4504 void R_GLSL_Restart_f(void)
4505 {
4506         unsigned int i, limit;
4507         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4508                 Mem_Free(glslshaderstring);
4509         glslshaderstring = NULL;
4510         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
4511                 Mem_Free(hlslshaderstring);
4512         hlslshaderstring = NULL;
4513         switch(vid.renderpath)
4514         {
4515         case RENDERPATH_D3D9:
4516 #ifdef SUPPORTD3D
4517                 {
4518                         r_hlsl_permutation_t *p;
4519                         r_hlsl_permutation = NULL;
4520                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4521                         for (i = 0;i < limit;i++)
4522                         {
4523                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4524                                 {
4525                                         if (p->vertexshader)
4526                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4527                                         if (p->pixelshader)
4528                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4529                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4530                                 }
4531                         }
4532                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4533                 }
4534 #endif
4535                 break;
4536         case RENDERPATH_D3D10:
4537                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4538                 break;
4539         case RENDERPATH_D3D11:
4540                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4541                 break;
4542         case RENDERPATH_GL20:
4543         case RENDERPATH_GLES2:
4544                 {
4545                         r_glsl_permutation_t *p;
4546                         r_glsl_permutation = NULL;
4547                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4548                         for (i = 0;i < limit;i++)
4549                         {
4550                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4551                                 {
4552                                         GL_Backend_FreeProgram(p->program);
4553                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4554                                 }
4555                         }
4556                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4557                 }
4558                 break;
4559         case RENDERPATH_GL13:
4560         case RENDERPATH_GL11:
4561                 break;
4562         case RENDERPATH_SOFT:
4563                 break;
4564         }
4565 }
4566
4567 void R_GLSL_DumpShader_f(void)
4568 {
4569         int i;
4570         qfile_t *file;
4571
4572         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4573         if (file)
4574         {
4575                 FS_Print(file, "/* The engine may define the following macros:\n");
4576                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4577                 for (i = 0;i < SHADERMODE_COUNT;i++)
4578                         FS_Print(file, glslshadermodeinfo[i].pretext);
4579                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4580                         FS_Print(file, shaderpermutationinfo[i].pretext);
4581                 FS_Print(file, "*/\n");
4582                 FS_Print(file, builtinshaderstring);
4583                 FS_Close(file);
4584                 Con_Printf("glsl/default.glsl written\n");
4585         }
4586         else
4587                 Con_Printf("failed to write to glsl/default.glsl\n");
4588
4589         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4590         if (file)
4591         {
4592                 FS_Print(file, "/* The engine may define the following macros:\n");
4593                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4594                 for (i = 0;i < SHADERMODE_COUNT;i++)
4595                         FS_Print(file, hlslshadermodeinfo[i].pretext);
4596                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4597                         FS_Print(file, shaderpermutationinfo[i].pretext);
4598                 FS_Print(file, "*/\n");
4599                 FS_Print(file, builtinhlslshaderstring);
4600                 FS_Close(file);
4601                 Con_Printf("hlsl/default.hlsl written\n");
4602         }
4603         else
4604                 Con_Printf("failed to write to hlsl/default.hlsl\n");
4605 }
4606
4607 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4608 {
4609         if (!second)
4610                 texturemode = GL_MODULATE;
4611         switch (vid.renderpath)
4612         {
4613         case RENDERPATH_D3D9:
4614 #ifdef SUPPORTD3D
4615                 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))));
4616                 R_Mesh_TexBind(GL20TU_FIRST , first );
4617                 R_Mesh_TexBind(GL20TU_SECOND, second);
4618 #endif
4619                 break;
4620         case RENDERPATH_D3D10:
4621                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4622                 break;
4623         case RENDERPATH_D3D11:
4624                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4625                 break;
4626         case RENDERPATH_GL20:
4627         case RENDERPATH_GLES2:
4628                 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))));
4629                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
4630                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
4631                 break;
4632         case RENDERPATH_GL13:
4633                 R_Mesh_TexBind(0, first );
4634                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4635                 R_Mesh_TexBind(1, second);
4636                 if (second)
4637                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4638                 break;
4639         case RENDERPATH_GL11:
4640                 R_Mesh_TexBind(0, first );
4641                 break;
4642         case RENDERPATH_SOFT:
4643                 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))));
4644                 R_Mesh_TexBind(GL20TU_FIRST , first );
4645                 R_Mesh_TexBind(GL20TU_SECOND, second);
4646                 break;
4647         }
4648 }
4649
4650 void R_SetupShader_DepthOrShadow(void)
4651 {
4652         switch (vid.renderpath)
4653         {
4654         case RENDERPATH_D3D9:
4655 #ifdef SUPPORTD3D
4656                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4657 #endif
4658                 break;
4659         case RENDERPATH_D3D10:
4660                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4661                 break;
4662         case RENDERPATH_D3D11:
4663                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4664                 break;
4665         case RENDERPATH_GL20:
4666         case RENDERPATH_GLES2:
4667                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4668                 break;
4669         case RENDERPATH_GL13:
4670                 R_Mesh_TexBind(0, 0);
4671                 R_Mesh_TexBind(1, 0);
4672                 break;
4673         case RENDERPATH_GL11:
4674                 R_Mesh_TexBind(0, 0);
4675                 break;
4676         case RENDERPATH_SOFT:
4677                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
4678                 break;
4679         }
4680 }
4681
4682 void R_SetupShader_ShowDepth(void)
4683 {
4684         switch (vid.renderpath)
4685         {
4686         case RENDERPATH_D3D9:
4687 #ifdef SUPPORTHLSL
4688                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
4689 #endif
4690                 break;
4691         case RENDERPATH_D3D10:
4692                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4693                 break;
4694         case RENDERPATH_D3D11:
4695                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4696                 break;
4697         case RENDERPATH_GL20:
4698         case RENDERPATH_GLES2:
4699                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4700                 break;
4701         case RENDERPATH_GL13:
4702                 break;
4703         case RENDERPATH_GL11:
4704                 break;
4705         case RENDERPATH_SOFT:
4706                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
4707                 break;
4708         }
4709 }
4710
4711 extern qboolean r_shadow_usingdeferredprepass;
4712 extern cvar_t r_shadow_deferred_8bitrange;
4713 extern rtexture_t *r_shadow_attenuationgradienttexture;
4714 extern rtexture_t *r_shadow_attenuation2dtexture;
4715 extern rtexture_t *r_shadow_attenuation3dtexture;
4716 extern qboolean r_shadow_usingshadowmap2d;
4717 extern qboolean r_shadow_usingshadowmaportho;
4718 extern float r_shadow_shadowmap_texturescale[2];
4719 extern float r_shadow_shadowmap_parameters[4];
4720 extern qboolean r_shadow_shadowmapvsdct;
4721 extern qboolean r_shadow_shadowmapsampler;
4722 extern int r_shadow_shadowmappcf;
4723 extern rtexture_t *r_shadow_shadowmap2dtexture;
4724 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
4725 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4726 extern matrix4x4_t r_shadow_shadowmapmatrix;
4727 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4728 extern int r_shadow_prepass_width;
4729 extern int r_shadow_prepass_height;
4730 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4731 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4732 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
4733 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4734 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4735 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4736 {
4737         // a blendfunc allows colormod if:
4738         // a) it can never keep the destination pixel invariant, or
4739         // b) it can keep the destination pixel invariant, and still can do so if colormodded
4740         // this is to prevent unintended side effects from colormod
4741
4742         // in formulas:
4743         // IF there is a (s, sa) for which for all (d, da),
4744         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4745         // THEN, for this (s, sa) and all (colormod, d, da):
4746         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4747         // OBVIOUSLY, this means that
4748         //   s*colormod * src(s*colormod, d, sa, da) = 0
4749         //   dst(s*colormod, d, sa, da)              = 1
4750
4751         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4752
4753         // main condition to leave dst color invariant:
4754         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4755         //   src == GL_ZERO:
4756         //     s * 0 + d * dst(s, d, sa, da) == d
4757         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4758         //       => colormod is a problem for GL_SRC_COLOR only
4759         //   src == GL_ONE:
4760         //     s + d * dst(s, d, sa, da) == d
4761         //       => s == 0
4762         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4763         //       => colormod is never problematic for these
4764         //   src == GL_SRC_COLOR:
4765         //     s*s + d * dst(s, d, sa, da) == d
4766         //       => s == 0
4767         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4768         //       => colormod is never problematic for these
4769         //   src == GL_ONE_MINUS_SRC_COLOR:
4770         //     s*(1-s) + d * dst(s, d, sa, da) == d
4771         //       => s == 0 or s == 1
4772         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4773         //       => colormod is a problem for GL_SRC_COLOR only
4774         //   src == GL_DST_COLOR
4775         //     s*d + d * dst(s, d, sa, da) == d
4776         //       => s == 1
4777         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4778         //       => colormod is always a problem
4779         //     or
4780         //       => s == 0
4781         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4782         //       => colormod is never problematic for these
4783         //       => BUT, we do not know s! We must assume it is problematic
4784         //       then... except in GL_ONE case, where we know all invariant
4785         //       cases are fine
4786         //   src == GL_ONE_MINUS_DST_COLOR
4787         //     s*(1-d) + d * dst(s, d, sa, da) == d
4788         //       => s == 0 (1-d is impossible to handle for our desired result)
4789         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4790         //       => colormod is never problematic for these
4791         //   src == GL_SRC_ALPHA
4792         //     s*sa + d * dst(s, d, sa, da) == d
4793         //       => s == 0, or sa == 0
4794         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4795         //       => colormod breaks in the case GL_SRC_COLOR only
4796         //   src == GL_ONE_MINUS_SRC_ALPHA
4797         //     s*(1-sa) + d * dst(s, d, sa, da) == d
4798         //       => s == 0, or sa == 1
4799         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4800         //       => colormod breaks in the case GL_SRC_COLOR only
4801         //   src == GL_DST_ALPHA
4802         //     s*da + d * dst(s, d, sa, da) == d
4803         //       => s == 0
4804         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4805         //       => colormod is never problematic for these
4806
4807         switch(src)
4808         {
4809                 case GL_ZERO:
4810                 case GL_ONE_MINUS_SRC_COLOR:
4811                 case GL_SRC_ALPHA:
4812                 case GL_ONE_MINUS_SRC_ALPHA:
4813                         if(dst == GL_SRC_COLOR)
4814                                 return false;
4815                         return true;
4816                 case GL_ONE:
4817                 case GL_SRC_COLOR:
4818                 case GL_ONE_MINUS_DST_COLOR:
4819                 case GL_DST_ALPHA:
4820                 case GL_ONE_MINUS_DST_ALPHA:
4821                         return true;
4822                 case GL_DST_COLOR:
4823                         if(dst == GL_ONE)
4824                                 return true;
4825                         return false;
4826                 default:
4827                         return false;
4828         }
4829 }
4830 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)
4831 {
4832         // select a permutation of the lighting shader appropriate to this
4833         // combination of texture, entity, light source, and fogging, only use the
4834         // minimum features necessary to avoid wasting rendering time in the
4835         // fragment shader on features that are not being used
4836         unsigned int permutation = 0;
4837         unsigned int mode = 0;
4838         qboolean allow_colormod;
4839         static float dummy_colormod[3] = {1, 1, 1};
4840         float *colormod = rsurface.colormod;
4841         float m16f[16];
4842         matrix4x4_t tempmatrix;
4843         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
4844         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4845                 permutation |= SHADERPERMUTATION_ALPHAKILL;
4846         if (rsurfacepass == RSURFPASS_BACKGROUND)
4847         {
4848                 // distorted background
4849                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4850                 {
4851                         mode = SHADERMODE_WATER;
4852                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4853                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4854                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
4855                         {
4856                                 // this is the right thing to do for wateralpha
4857                                 GL_BlendFunc(GL_ONE, GL_ZERO);
4858                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4859                         }
4860                         else
4861                         {
4862                                 // this is the right thing to do for entity alpha
4863                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4864                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4865                         }
4866                 }
4867                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4868                 {
4869                         mode = SHADERMODE_REFRACTION;
4870                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4871                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4872                 }
4873                 else
4874                 {
4875                         mode = SHADERMODE_GENERIC;
4876                         permutation |= SHADERPERMUTATION_DIFFUSE;
4877                         GL_BlendFunc(GL_ONE, GL_ZERO);
4878                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4879                 }
4880         }
4881         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4882         {
4883                 if (r_glsl_offsetmapping.integer)
4884                 {
4885                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4886                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4887                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4888                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4889                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4890                         {
4891                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4892                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4893                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4894                         }
4895                 }
4896                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4897                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4898                 // normalmap (deferred prepass), may use alpha test on diffuse
4899                 mode = SHADERMODE_DEFERREDGEOMETRY;
4900                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4901                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4902                 GL_BlendFunc(GL_ONE, GL_ZERO);
4903                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4904         }
4905         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4906         {
4907                 if (r_glsl_offsetmapping.integer)
4908                 {
4909                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4910                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4911                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4912                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4913                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4914                         {
4915                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4916                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4917                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4918                         }
4919                 }
4920                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4921                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4922                 // light source
4923                 mode = SHADERMODE_LIGHTSOURCE;
4924                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4925                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4926                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4927                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4928                 if (diffusescale > 0)
4929                         permutation |= SHADERPERMUTATION_DIFFUSE;
4930                 if (specularscale > 0)
4931                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4932                 if (r_refdef.fogenabled)
4933                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4934                 if (rsurface.texture->colormapping)
4935                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4936                 if (r_shadow_usingshadowmap2d)
4937                 {
4938                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4939                         if(r_shadow_shadowmapvsdct)
4940                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4941
4942                         if (r_shadow_shadowmapsampler)
4943                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4944                         if (r_shadow_shadowmappcf > 1)
4945                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4946                         else if (r_shadow_shadowmappcf)
4947                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4948                 }
4949                 if (rsurface.texture->reflectmasktexture)
4950                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4951                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4952                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
4953         }
4954         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4955         {
4956                 if (r_glsl_offsetmapping.integer)
4957                 {
4958                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4959                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4960                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4961                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4962                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4963                         {
4964                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4965                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4966                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4967                         }
4968                 }
4969                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4970                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4971                 // unshaded geometry (fullbright or ambient model lighting)
4972                 mode = SHADERMODE_FLATCOLOR;
4973                 ambientscale = diffusescale = specularscale = 0;
4974                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4975                         permutation |= SHADERPERMUTATION_GLOW;
4976                 if (r_refdef.fogenabled)
4977                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4978                 if (rsurface.texture->colormapping)
4979                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4980                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4981                 {
4982                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4983                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4984
4985                         if (r_shadow_shadowmapsampler)
4986                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4987                         if (r_shadow_shadowmappcf > 1)
4988                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4989                         else if (r_shadow_shadowmappcf)
4990                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4991                 }
4992                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4993                         permutation |= SHADERPERMUTATION_REFLECTION;
4994                 if (rsurface.texture->reflectmasktexture)
4995                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4996                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4997                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4998         }
4999         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5000         {
5001                 if (r_glsl_offsetmapping.integer)
5002                 {
5003                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5004                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5005                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5006                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5007                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5008                         {
5009                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5010                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5011                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5012                         }
5013                 }
5014                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5015                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5016                 // directional model lighting
5017                 mode = SHADERMODE_LIGHTDIRECTION;
5018                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5019                         permutation |= SHADERPERMUTATION_GLOW;
5020                 permutation |= SHADERPERMUTATION_DIFFUSE;
5021                 if (specularscale > 0)
5022                         permutation |= SHADERPERMUTATION_SPECULAR;
5023                 if (r_refdef.fogenabled)
5024                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5025                 if (rsurface.texture->colormapping)
5026                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5027                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5028                 {
5029                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5030                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5031
5032                         if (r_shadow_shadowmapsampler)
5033                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5034                         if (r_shadow_shadowmappcf > 1)
5035                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5036                         else if (r_shadow_shadowmappcf)
5037                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5038                 }
5039                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5040                         permutation |= SHADERPERMUTATION_REFLECTION;
5041                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5042                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5043                 if (rsurface.texture->reflectmasktexture)
5044                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5045                 if (r_shadow_bouncegridtexture)
5046                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
5047                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5048                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5049         }
5050         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5051         {
5052                 if (r_glsl_offsetmapping.integer)
5053                 {
5054                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5055                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5056                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5057                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5058                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5059                         {
5060                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5061                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5062                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5063                         }
5064                 }
5065                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5066                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5067                 // ambient model lighting
5068                 mode = SHADERMODE_LIGHTDIRECTION;
5069                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5070                         permutation |= SHADERPERMUTATION_GLOW;
5071                 if (r_refdef.fogenabled)
5072                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5073                 if (rsurface.texture->colormapping)
5074                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5075                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5076                 {
5077                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5078                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5079
5080                         if (r_shadow_shadowmapsampler)
5081                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5082                         if (r_shadow_shadowmappcf > 1)
5083                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5084                         else if (r_shadow_shadowmappcf)
5085                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5086                 }
5087                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5088                         permutation |= SHADERPERMUTATION_REFLECTION;
5089                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5090                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5091                 if (rsurface.texture->reflectmasktexture)
5092                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5093                 if (r_shadow_bouncegridtexture)
5094                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
5095                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5096                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5097         }
5098         else
5099         {
5100                 if (r_glsl_offsetmapping.integer)
5101                 {
5102                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5103                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5104                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5105                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5106                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5107                         {
5108                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5109                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5110                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5111                         }
5112                 }
5113                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5114                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5115                 // lightmapped wall
5116                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5117                         permutation |= SHADERPERMUTATION_GLOW;
5118                 if (r_refdef.fogenabled)
5119                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5120                 if (rsurface.texture->colormapping)
5121                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5122                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5123                 {
5124                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5125                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5126
5127                         if (r_shadow_shadowmapsampler)
5128                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5129                         if (r_shadow_shadowmappcf > 1)
5130                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5131                         else if (r_shadow_shadowmappcf)
5132                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5133                 }
5134                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5135                         permutation |= SHADERPERMUTATION_REFLECTION;
5136                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5137                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5138                 if (rsurface.texture->reflectmasktexture)
5139                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5140                 if (FAKELIGHT_ENABLED)
5141                 {
5142                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5143                         mode = SHADERMODE_FAKELIGHT;
5144                         permutation |= SHADERPERMUTATION_DIFFUSE;
5145                         if (specularscale > 0)
5146                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5147                 }
5148                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5149                 {
5150                         // deluxemapping (light direction texture)
5151                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5152                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5153                         else
5154                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5155                         permutation |= SHADERPERMUTATION_DIFFUSE;
5156                         if (specularscale > 0)
5157                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5158                 }
5159                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5160                 {
5161                         // fake deluxemapping (uniform light direction in tangentspace)
5162                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5163                         permutation |= SHADERPERMUTATION_DIFFUSE;
5164                         if (specularscale > 0)
5165                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5166                 }
5167                 else if (rsurface.uselightmaptexture)
5168                 {
5169                         // ordinary lightmapping (q1bsp, q3bsp)
5170                         mode = SHADERMODE_LIGHTMAP;
5171                 }
5172                 else
5173                 {
5174                         // ordinary vertex coloring (q3bsp)
5175                         mode = SHADERMODE_VERTEXCOLOR;
5176                 }
5177                 if (r_shadow_bouncegridtexture)
5178                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
5179                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5180                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5181         }
5182         if(!allow_colormod)
5183                 colormod = dummy_colormod;
5184         switch(vid.renderpath)
5185         {
5186         case RENDERPATH_D3D9:
5187 #ifdef SUPPORTD3D
5188                 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);
5189                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5190                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5191                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5192                 if (mode == SHADERMODE_LIGHTSOURCE)
5193                 {
5194                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5195                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5196                 }
5197                 else
5198                 {
5199                         if (mode == SHADERMODE_LIGHTDIRECTION)
5200                         {
5201                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5202                         }
5203                 }
5204                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5205                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5206                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5207                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5208                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5209
5210                 if (mode == SHADERMODE_LIGHTSOURCE)
5211                 {
5212                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5213                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5214                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5215                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5216                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5217
5218                         // additive passes are only darkened by fog, not tinted
5219                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5220                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5221                 }
5222                 else
5223                 {
5224                         if (mode == SHADERMODE_FLATCOLOR)
5225                         {
5226                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5227                         }
5228                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5229                         {
5230                                 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]);
5231                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5232                                 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);
5233                                 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);
5234                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5235                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5236                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5237                         }
5238                         else
5239                         {
5240                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5241                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5242                                 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);
5243                                 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);
5244                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5245                         }
5246                         // additive passes are only darkened by fog, not tinted
5247                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5248                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5249                         else
5250                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5251                         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);
5252                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5253                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5254                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5255                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5256                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5257                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5258                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5259                         if (mode == SHADERMODE_WATER)
5260                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5261                 }
5262                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5263                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5264                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5265                 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));
5266                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5267                 if (rsurface.texture->pantstexture)
5268                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5269                 else
5270                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5271                 if (rsurface.texture->shirttexture)
5272                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5273                 else
5274                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5275                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5276                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5277                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5278                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5279                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5280                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5281                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5282
5283                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5284                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5285                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5286                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5287                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5288                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5289                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5290                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5291                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5292                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5293                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5294                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5295                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5296                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5297                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5298                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5299                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5300                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5301                 {
5302                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5303                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5304                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5305                 }
5306                 else
5307                 {
5308                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5309                 }
5310 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5311 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5312                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5313                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5314                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5315                 {
5316                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5317                         if (rsurface.rtlight)
5318                         {
5319                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5320                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5321                         }
5322                 }
5323 #endif
5324                 break;
5325         case RENDERPATH_D3D10:
5326                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5327                 break;
5328         case RENDERPATH_D3D11:
5329                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5330                 break;
5331         case RENDERPATH_GL20:
5332         case RENDERPATH_GLES2:
5333                 if (!vid.useinterleavedarrays)
5334                 {
5335                         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);
5336                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5337                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5338                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5339                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5340                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5341                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5342                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5343                 }
5344                 else
5345                 {
5346                         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);
5347                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5348                 }
5349                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5350                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5351                 if (mode == SHADERMODE_LIGHTSOURCE)
5352                 {
5353                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5354                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5355                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5356                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5357                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5358                         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);
5359         
5360                         // additive passes are only darkened by fog, not tinted
5361                         if (r_glsl_permutation->loc_FogColor >= 0)
5362                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5363                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5364                 }
5365                 else
5366                 {
5367                         if (mode == SHADERMODE_FLATCOLOR)
5368                         {
5369                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5370                         }
5371                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5372                         {
5373                                 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]);
5374                                 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]);
5375                                 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);
5376                                 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);
5377                                 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);
5378                                 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]);
5379                                 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]);
5380                         }
5381                         else
5382                         {
5383                                 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]);
5384                                 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]);
5385                                 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);
5386                                 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);
5387                                 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);
5388                         }
5389                         // additive passes are only darkened by fog, not tinted
5390                         if (r_glsl_permutation->loc_FogColor >= 0)
5391                         {
5392                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5393                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5394                                 else
5395                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5396                         }
5397                         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);
5398                         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]);
5399                         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]);
5400                         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]);
5401                         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]);
5402                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5403                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5404                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5405                         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]);
5406                 }
5407                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5408                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5409                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5410                 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]);
5411                 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]);
5412
5413                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5414                 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));
5415                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5416                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5417                 {
5418                         if (rsurface.texture->pantstexture)
5419                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5420                         else
5421                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5422                 }
5423                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5424                 {
5425                         if (rsurface.texture->shirttexture)
5426                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5427                         else
5428                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5429                 }
5430                 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]);
5431                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5432                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5433                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5434                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5435                 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]);
5436                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5437                 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);}
5438                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
5439
5440                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
5441                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
5442                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
5443                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
5444                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
5445                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
5446                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
5447                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
5448                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
5449                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
5450                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
5451                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
5452                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
5453                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
5454                 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);
5455                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
5456                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
5457                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5458                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5459                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
5460                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5461                 {
5462                         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);
5463                         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);
5464                         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);
5465                 }
5466                 else
5467                 {
5468                         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);
5469                 }
5470                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
5471                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
5472                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
5473                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
5474                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5475                 {
5476                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
5477                         if (rsurface.rtlight)
5478                         {
5479                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
5480                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
5481                         }
5482                 }
5483                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
5484                 CHECKGLERROR
5485                 break;
5486         case RENDERPATH_GL13:
5487         case RENDERPATH_GL11:
5488                 break;
5489         case RENDERPATH_SOFT:
5490                 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);
5491                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
5492                 R_SetupShader_SetPermutationSoft(mode, permutation);
5493                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
5494                 if (mode == SHADERMODE_LIGHTSOURCE)
5495                 {
5496                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
5497                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5498                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5499                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5500                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5501                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5502         
5503                         // additive passes are only darkened by fog, not tinted
5504                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5505                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5506                 }
5507                 else
5508                 {
5509                         if (mode == SHADERMODE_FLATCOLOR)
5510                         {
5511                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5512                         }
5513                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5514                         {
5515                                 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]);
5516                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5517                                 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);
5518                                 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);
5519                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5520                                 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]);
5521                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5522                         }
5523                         else
5524                         {
5525                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5526                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5527                                 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);
5528                                 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);
5529                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5530                         }
5531                         // additive passes are only darkened by fog, not tinted
5532                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5533                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5534                         else
5535                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5536                         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);
5537                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5538                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5539                         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]);
5540                         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]);
5541                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5542                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
5543                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5544                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5545                 }
5546                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
5547                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
5548                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
5549                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5550                 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]);
5551
5552                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5553                 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));
5554                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5555                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
5556                 {
5557                         if (rsurface.texture->pantstexture)
5558                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5559                         else
5560                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
5561                 }
5562                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
5563                 {
5564                         if (rsurface.texture->shirttexture)
5565                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5566                         else
5567                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
5568                 }
5569                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5570                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
5571                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
5572                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
5573                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5574                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5575                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5576
5577                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5578                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5579                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5580                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5581                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5582                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5583                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5584                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5585                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5586                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5587                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5588                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5589                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5590                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5591                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5592                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5593                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5594                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5595                 {
5596                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5597                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5598                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5599                 }
5600                 else
5601                 {
5602                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5603                 }
5604 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5605 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5606                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5607                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5608                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5609                 {
5610                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5611                         if (rsurface.rtlight)
5612                         {
5613                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5614                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5615                         }
5616                 }
5617                 break;
5618         }
5619 }
5620
5621 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5622 {
5623         // select a permutation of the lighting shader appropriate to this
5624         // combination of texture, entity, light source, and fogging, only use the
5625         // minimum features necessary to avoid wasting rendering time in the
5626         // fragment shader on features that are not being used
5627         unsigned int permutation = 0;
5628         unsigned int mode = 0;
5629         const float *lightcolorbase = rtlight->currentcolor;
5630         float ambientscale = rtlight->ambientscale;
5631         float diffusescale = rtlight->diffusescale;
5632         float specularscale = rtlight->specularscale;
5633         // this is the location of the light in view space
5634         vec3_t viewlightorigin;
5635         // this transforms from view space (camera) to light space (cubemap)
5636         matrix4x4_t viewtolight;
5637         matrix4x4_t lighttoview;
5638         float viewtolight16f[16];
5639         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5640         // light source
5641         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5642         if (rtlight->currentcubemap != r_texture_whitecube)
5643                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5644         if (diffusescale > 0)
5645                 permutation |= SHADERPERMUTATION_DIFFUSE;
5646         if (specularscale > 0)
5647                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5648         if (r_shadow_usingshadowmap2d)
5649         {
5650                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5651                 if (r_shadow_shadowmapvsdct)
5652                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5653
5654                 if (r_shadow_shadowmapsampler)
5655                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5656                 if (r_shadow_shadowmappcf > 1)
5657                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5658                 else if (r_shadow_shadowmappcf)
5659                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5660         }
5661         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5662         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5663         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5664         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5665         switch(vid.renderpath)
5666         {
5667         case RENDERPATH_D3D9:
5668 #ifdef SUPPORTD3D
5669                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5670                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5671                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
5672                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5673                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5674                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5675                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5676                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5677                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5678                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5679                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5680
5681                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5682                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
5683                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5684                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5685                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
5686                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5687 #endif
5688                 break;
5689         case RENDERPATH_D3D10:
5690                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5691                 break;
5692         case RENDERPATH_D3D11:
5693                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5694                 break;
5695         case RENDERPATH_GL20:
5696         case RENDERPATH_GLES2:
5697                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5698                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5699                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5700                 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);
5701                 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);
5702                 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);
5703                 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]);
5704                 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]);
5705                 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));
5706                 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]);
5707                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
5708
5709                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
5710                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
5711                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
5712                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
5713                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
5714                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
5715                 break;
5716         case RENDERPATH_GL13:
5717         case RENDERPATH_GL11:
5718                 break;
5719         case RENDERPATH_SOFT:
5720                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5721                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5722                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
5723                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5724                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5725                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5726                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5727                 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]);
5728                 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));
5729                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5730                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5731
5732                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5733                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5734                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5735                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5736                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5737                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5738                 break;
5739         }
5740 }
5741
5742 #define SKINFRAME_HASH 1024
5743
5744 typedef struct
5745 {
5746         int loadsequence; // incremented each level change
5747         memexpandablearray_t array;
5748         skinframe_t *hash[SKINFRAME_HASH];
5749 }
5750 r_skinframe_t;
5751 r_skinframe_t r_skinframe;
5752
5753 void R_SkinFrame_PrepareForPurge(void)
5754 {
5755         r_skinframe.loadsequence++;
5756         // wrap it without hitting zero
5757         if (r_skinframe.loadsequence >= 200)
5758                 r_skinframe.loadsequence = 1;
5759 }
5760
5761 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5762 {
5763         if (!skinframe)
5764                 return;
5765         // mark the skinframe as used for the purging code
5766         skinframe->loadsequence = r_skinframe.loadsequence;
5767 }
5768
5769 void R_SkinFrame_Purge(void)
5770 {
5771         int i;
5772         skinframe_t *s;
5773         for (i = 0;i < SKINFRAME_HASH;i++)
5774         {
5775                 for (s = r_skinframe.hash[i];s;s = s->next)
5776                 {
5777                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5778                         {
5779                                 if (s->merged == s->base)
5780                                         s->merged = NULL;
5781                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5782                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5783                                 R_PurgeTexture(s->merged);s->merged = NULL;
5784                                 R_PurgeTexture(s->base  );s->base   = NULL;
5785                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5786                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5787                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5788                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5789                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5790                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5791                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5792                                 s->loadsequence = 0;
5793                         }
5794                 }
5795         }
5796 }
5797
5798 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5799         skinframe_t *item;
5800         char basename[MAX_QPATH];
5801
5802         Image_StripImageExtension(name, basename, sizeof(basename));
5803
5804         if( last == NULL ) {
5805                 int hashindex;
5806                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5807                 item = r_skinframe.hash[hashindex];
5808         } else {
5809                 item = last->next;
5810         }
5811
5812         // linearly search through the hash bucket
5813         for( ; item ; item = item->next ) {
5814                 if( !strcmp( item->basename, basename ) ) {
5815                         return item;
5816                 }
5817         }
5818         return NULL;
5819 }
5820
5821 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5822 {
5823         skinframe_t *item;
5824         int hashindex;
5825         char basename[MAX_QPATH];
5826
5827         Image_StripImageExtension(name, basename, sizeof(basename));
5828
5829         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5830         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5831                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5832                         break;
5833
5834         if (!item) {
5835                 rtexture_t *dyntexture;
5836                 // check whether its a dynamic texture
5837                 dyntexture = CL_GetDynTexture( basename );
5838                 if (!add && !dyntexture)
5839                         return NULL;
5840                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5841                 memset(item, 0, sizeof(*item));
5842                 strlcpy(item->basename, basename, sizeof(item->basename));
5843                 item->base = dyntexture; // either NULL or dyntexture handle
5844                 item->textureflags = textureflags;
5845                 item->comparewidth = comparewidth;
5846                 item->compareheight = compareheight;
5847                 item->comparecrc = comparecrc;
5848                 item->next = r_skinframe.hash[hashindex];
5849                 r_skinframe.hash[hashindex] = item;
5850         }
5851         else if( item->base == NULL )
5852         {
5853                 rtexture_t *dyntexture;
5854                 // check whether its a dynamic texture
5855                 // 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]
5856                 dyntexture = CL_GetDynTexture( basename );
5857                 item->base = dyntexture; // either NULL or dyntexture handle
5858         }
5859
5860         R_SkinFrame_MarkUsed(item);
5861         return item;
5862 }
5863
5864 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5865         { \
5866                 unsigned long long avgcolor[5], wsum; \
5867                 int pix, comp, w; \
5868                 avgcolor[0] = 0; \
5869                 avgcolor[1] = 0; \
5870                 avgcolor[2] = 0; \
5871                 avgcolor[3] = 0; \
5872                 avgcolor[4] = 0; \
5873                 wsum = 0; \
5874                 for(pix = 0; pix < cnt; ++pix) \
5875                 { \
5876                         w = 0; \
5877                         for(comp = 0; comp < 3; ++comp) \
5878                                 w += getpixel; \
5879                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5880                         { \
5881                                 ++wsum; \
5882                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5883                                 w = getpixel; \
5884                                 for(comp = 0; comp < 3; ++comp) \
5885                                         avgcolor[comp] += getpixel * w; \
5886                                 avgcolor[3] += w; \
5887                         } \
5888                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5889                         avgcolor[4] += getpixel; \
5890                 } \
5891                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5892                         avgcolor[3] = 1; \
5893                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5894                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5895                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5896                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5897         }
5898
5899 extern cvar_t gl_picmip;
5900 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5901 {
5902         int j;
5903         unsigned char *pixels;
5904         unsigned char *bumppixels;
5905         unsigned char *basepixels = NULL;
5906         int basepixels_width = 0;
5907         int basepixels_height = 0;
5908         skinframe_t *skinframe;
5909         rtexture_t *ddsbase = NULL;
5910         qboolean ddshasalpha = false;
5911         float ddsavgcolor[4];
5912         char basename[MAX_QPATH];
5913         int miplevel = R_PicmipForFlags(textureflags);
5914         int savemiplevel = miplevel;
5915         int mymiplevel;
5916
5917         if (cls.state == ca_dedicated)
5918                 return NULL;
5919
5920         // return an existing skinframe if already loaded
5921         // if loading of the first image fails, don't make a new skinframe as it
5922         // would cause all future lookups of this to be missing
5923         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5924         if (skinframe && skinframe->base)
5925                 return skinframe;
5926
5927         Image_StripImageExtension(name, basename, sizeof(basename));
5928
5929         // check for DDS texture file first
5930         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5931         {
5932                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
5933                 if (basepixels == NULL)
5934                         return NULL;
5935         }
5936
5937         // FIXME handle miplevel
5938
5939         if (developer_loading.integer)
5940                 Con_Printf("loading skin \"%s\"\n", name);
5941
5942         // we've got some pixels to store, so really allocate this new texture now
5943         if (!skinframe)
5944                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5945         skinframe->stain = NULL;
5946         skinframe->merged = NULL;
5947         skinframe->base = NULL;
5948         skinframe->pants = NULL;
5949         skinframe->shirt = NULL;
5950         skinframe->nmap = NULL;
5951         skinframe->gloss = NULL;
5952         skinframe->glow = NULL;
5953         skinframe->fog = NULL;
5954         skinframe->reflect = NULL;
5955         skinframe->hasalpha = false;
5956
5957         if (ddsbase)
5958         {
5959                 skinframe->base = ddsbase;
5960                 skinframe->hasalpha = ddshasalpha;
5961                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5962                 if (r_loadfog && skinframe->hasalpha)
5963                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
5964                 //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]);
5965         }
5966         else
5967         {
5968                 basepixels_width = image_width;
5969                 basepixels_height = image_height;
5970                 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);
5971                 if (textureflags & TEXF_ALPHA)
5972                 {
5973                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5974                         {
5975                                 if (basepixels[j] < 255)
5976                                 {
5977                                         skinframe->hasalpha = true;
5978                                         break;
5979                                 }
5980                         }
5981                         if (r_loadfog && skinframe->hasalpha)
5982                         {
5983                                 // has transparent pixels
5984                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5985                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5986                                 {
5987                                         pixels[j+0] = 255;
5988                                         pixels[j+1] = 255;
5989                                         pixels[j+2] = 255;
5990                                         pixels[j+3] = basepixels[j+3];
5991                                 }
5992                                 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);
5993                                 Mem_Free(pixels);
5994                         }
5995                 }
5996                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5997                 //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]);
5998                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5999                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6000                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6001                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6002         }
6003
6004         if (r_loaddds)
6005         {
6006                 mymiplevel = savemiplevel;
6007                 if (r_loadnormalmap)
6008                         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);
6009                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6010                 if (r_loadgloss)
6011                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6012                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6013                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6014                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6015         }
6016
6017         // _norm is the name used by tenebrae and has been adopted as standard
6018         if (r_loadnormalmap && skinframe->nmap == NULL)
6019         {
6020                 mymiplevel = savemiplevel;
6021                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6022                 {
6023                         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);
6024                         Mem_Free(pixels);
6025                         pixels = NULL;
6026                 }
6027                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6028                 {
6029                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6030                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6031                         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);
6032                         Mem_Free(pixels);
6033                         Mem_Free(bumppixels);
6034                 }
6035                 else if (r_shadow_bumpscale_basetexture.value > 0)
6036                 {
6037                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6038                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6039                         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);
6040                         Mem_Free(pixels);
6041                 }
6042                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6043                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6044         }
6045
6046         // _luma is supported only for tenebrae compatibility
6047         // _glow is the preferred name
6048         mymiplevel = savemiplevel;
6049         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))))
6050         {
6051                 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);
6052                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6053                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6054                 Mem_Free(pixels);pixels = NULL;
6055         }
6056
6057         mymiplevel = savemiplevel;
6058         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6059         {
6060                 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);
6061                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6062                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6063                 Mem_Free(pixels);
6064                 pixels = NULL;
6065         }
6066
6067         mymiplevel = savemiplevel;
6068         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6069         {
6070                 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);
6071                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6072                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6073                 Mem_Free(pixels);
6074                 pixels = NULL;
6075         }
6076
6077         mymiplevel = savemiplevel;
6078         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6079         {
6080                 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);
6081                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6082                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6083                 Mem_Free(pixels);
6084                 pixels = NULL;
6085         }
6086
6087         mymiplevel = savemiplevel;
6088         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6089         {
6090                 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);
6091                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6092                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6093                 Mem_Free(pixels);
6094                 pixels = NULL;
6095         }
6096
6097         if (basepixels)
6098                 Mem_Free(basepixels);
6099
6100         return skinframe;
6101 }
6102
6103 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6104 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6105 {
6106         int i;
6107         unsigned char *temp1, *temp2;
6108         skinframe_t *skinframe;
6109
6110         if (cls.state == ca_dedicated)
6111                 return NULL;
6112
6113         // if already loaded just return it, otherwise make a new skinframe
6114         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6115         if (skinframe && skinframe->base)
6116                 return skinframe;
6117
6118         skinframe->stain = NULL;
6119         skinframe->merged = NULL;
6120         skinframe->base = NULL;
6121         skinframe->pants = NULL;
6122         skinframe->shirt = NULL;
6123         skinframe->nmap = NULL;
6124         skinframe->gloss = NULL;
6125         skinframe->glow = NULL;
6126         skinframe->fog = NULL;
6127         skinframe->reflect = NULL;
6128         skinframe->hasalpha = false;
6129
6130         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6131         if (!skindata)
6132                 return NULL;
6133
6134         if (developer_loading.integer)
6135                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6136
6137         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6138         {
6139                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6140                 temp2 = temp1 + width * height * 4;
6141                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6142                 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);
6143                 Mem_Free(temp1);
6144         }
6145         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6146         if (textureflags & TEXF_ALPHA)
6147         {
6148                 for (i = 3;i < width * height * 4;i += 4)
6149                 {
6150                         if (skindata[i] < 255)
6151                         {
6152                                 skinframe->hasalpha = true;
6153                                 break;
6154                         }
6155                 }
6156                 if (r_loadfog && skinframe->hasalpha)
6157                 {
6158                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6159                         memcpy(fogpixels, skindata, width * height * 4);
6160                         for (i = 0;i < width * height * 4;i += 4)
6161                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6162                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6163                         Mem_Free(fogpixels);
6164                 }
6165         }
6166
6167         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6168         //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]);
6169
6170         return skinframe;
6171 }
6172
6173 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6174 {
6175         int i;
6176         int featuresmask;
6177         skinframe_t *skinframe;
6178
6179         if (cls.state == ca_dedicated)
6180                 return NULL;
6181
6182         // if already loaded just return it, otherwise make a new skinframe
6183         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6184         if (skinframe && skinframe->base)
6185                 return skinframe;
6186
6187         skinframe->stain = NULL;
6188         skinframe->merged = NULL;
6189         skinframe->base = NULL;
6190         skinframe->pants = NULL;
6191         skinframe->shirt = NULL;
6192         skinframe->nmap = NULL;
6193         skinframe->gloss = NULL;
6194         skinframe->glow = NULL;
6195         skinframe->fog = NULL;
6196         skinframe->reflect = NULL;
6197         skinframe->hasalpha = false;
6198
6199         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6200         if (!skindata)
6201                 return NULL;
6202
6203         if (developer_loading.integer)
6204                 Con_Printf("loading quake skin \"%s\"\n", name);
6205
6206         // 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)
6207         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6208         memcpy(skinframe->qpixels, skindata, width*height);
6209         skinframe->qwidth = width;
6210         skinframe->qheight = height;
6211
6212         featuresmask = 0;
6213         for (i = 0;i < width * height;i++)
6214                 featuresmask |= palette_featureflags[skindata[i]];
6215
6216         skinframe->hasalpha = false;
6217         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6218         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6219         skinframe->qgeneratemerged = true;
6220         skinframe->qgeneratebase = skinframe->qhascolormapping;
6221         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6222
6223         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6224         //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]);
6225
6226         return skinframe;
6227 }
6228
6229 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6230 {
6231         int width;
6232         int height;
6233         unsigned char *skindata;
6234
6235         if (!skinframe->qpixels)
6236                 return;
6237
6238         if (!skinframe->qhascolormapping)
6239                 colormapped = false;
6240
6241         if (colormapped)
6242         {
6243                 if (!skinframe->qgeneratebase)
6244                         return;
6245         }
6246         else
6247         {
6248                 if (!skinframe->qgeneratemerged)
6249                         return;
6250         }
6251
6252         width = skinframe->qwidth;
6253         height = skinframe->qheight;
6254         skindata = skinframe->qpixels;
6255
6256         if (skinframe->qgeneratenmap)
6257         {
6258                 unsigned char *temp1, *temp2;
6259                 skinframe->qgeneratenmap = false;
6260                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6261                 temp2 = temp1 + width * height * 4;
6262                 // use either a custom palette or the quake palette
6263                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6264                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6265                 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);
6266                 Mem_Free(temp1);
6267         }
6268
6269         if (skinframe->qgenerateglow)
6270         {
6271                 skinframe->qgenerateglow = false;
6272                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6273         }
6274
6275         if (colormapped)
6276         {
6277                 skinframe->qgeneratebase = false;
6278                 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);
6279                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6280                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6281         }
6282         else
6283         {
6284                 skinframe->qgeneratemerged = false;
6285                 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);
6286         }
6287
6288         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6289         {
6290                 Mem_Free(skinframe->qpixels);
6291                 skinframe->qpixels = NULL;
6292         }
6293 }
6294
6295 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)
6296 {
6297         int i;
6298         skinframe_t *skinframe;
6299
6300         if (cls.state == ca_dedicated)
6301                 return NULL;
6302
6303         // if already loaded just return it, otherwise make a new skinframe
6304         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6305         if (skinframe && skinframe->base)
6306                 return skinframe;
6307
6308         skinframe->stain = NULL;
6309         skinframe->merged = NULL;
6310         skinframe->base = NULL;
6311         skinframe->pants = NULL;
6312         skinframe->shirt = NULL;
6313         skinframe->nmap = NULL;
6314         skinframe->gloss = NULL;
6315         skinframe->glow = NULL;
6316         skinframe->fog = NULL;
6317         skinframe->reflect = NULL;
6318         skinframe->hasalpha = false;
6319
6320         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6321         if (!skindata)
6322                 return NULL;
6323
6324         if (developer_loading.integer)
6325                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6326
6327         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6328         if (textureflags & TEXF_ALPHA)
6329         {
6330                 for (i = 0;i < width * height;i++)
6331                 {
6332                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6333                         {
6334                                 skinframe->hasalpha = true;
6335                                 break;
6336                         }
6337                 }
6338                 if (r_loadfog && skinframe->hasalpha)
6339                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6340         }
6341
6342         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6343         //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]);
6344
6345         return skinframe;
6346 }
6347
6348 skinframe_t *R_SkinFrame_LoadMissing(void)
6349 {
6350         skinframe_t *skinframe;
6351
6352         if (cls.state == ca_dedicated)
6353                 return NULL;
6354
6355         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6356         skinframe->stain = NULL;
6357         skinframe->merged = NULL;
6358         skinframe->base = NULL;
6359         skinframe->pants = NULL;
6360         skinframe->shirt = NULL;
6361         skinframe->nmap = NULL;
6362         skinframe->gloss = NULL;
6363         skinframe->glow = NULL;
6364         skinframe->fog = NULL;
6365         skinframe->reflect = NULL;
6366         skinframe->hasalpha = false;
6367
6368         skinframe->avgcolor[0] = rand() / RAND_MAX;
6369         skinframe->avgcolor[1] = rand() / RAND_MAX;
6370         skinframe->avgcolor[2] = rand() / RAND_MAX;
6371         skinframe->avgcolor[3] = 1;
6372
6373         return skinframe;
6374 }
6375
6376 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6377 typedef struct suffixinfo_s
6378 {
6379         const char *suffix;
6380         qboolean flipx, flipy, flipdiagonal;
6381 }
6382 suffixinfo_t;
6383 static suffixinfo_t suffix[3][6] =
6384 {
6385         {
6386                 {"px",   false, false, false},
6387                 {"nx",   false, false, false},
6388                 {"py",   false, false, false},
6389                 {"ny",   false, false, false},
6390                 {"pz",   false, false, false},
6391                 {"nz",   false, false, false}
6392         },
6393         {
6394                 {"posx", false, false, false},
6395                 {"negx", false, false, false},
6396                 {"posy", false, false, false},
6397                 {"negy", false, false, false},
6398                 {"posz", false, false, false},
6399                 {"negz", false, false, false}
6400         },
6401         {
6402                 {"rt",    true, false,  true},
6403                 {"lf",   false,  true,  true},
6404                 {"ft",    true,  true, false},
6405                 {"bk",   false, false, false},
6406                 {"up",    true, false,  true},
6407                 {"dn",    true, false,  true}
6408         }
6409 };
6410
6411 static int componentorder[4] = {0, 1, 2, 3};
6412
6413 rtexture_t *R_LoadCubemap(const char *basename)
6414 {
6415         int i, j, cubemapsize;
6416         unsigned char *cubemappixels, *image_buffer;
6417         rtexture_t *cubemaptexture;
6418         char name[256];
6419         // must start 0 so the first loadimagepixels has no requested width/height
6420         cubemapsize = 0;
6421         cubemappixels = NULL;
6422         cubemaptexture = NULL;
6423         // keep trying different suffix groups (posx, px, rt) until one loads
6424         for (j = 0;j < 3 && !cubemappixels;j++)
6425         {
6426                 // load the 6 images in the suffix group
6427                 for (i = 0;i < 6;i++)
6428                 {
6429                         // generate an image name based on the base and and suffix
6430                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6431                         // load it
6432                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6433                         {
6434                                 // an image loaded, make sure width and height are equal
6435                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6436                                 {
6437                                         // if this is the first image to load successfully, allocate the cubemap memory
6438                                         if (!cubemappixels && image_width >= 1)
6439                                         {
6440                                                 cubemapsize = image_width;
6441                                                 // note this clears to black, so unavailable sides are black
6442                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6443                                         }
6444                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6445                                         if (cubemappixels)
6446                                                 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);
6447                                 }
6448                                 else
6449                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6450                                 // free the image
6451                                 Mem_Free(image_buffer);
6452                         }
6453                 }
6454         }
6455         // if a cubemap loaded, upload it
6456         if (cubemappixels)
6457         {
6458                 if (developer_loading.integer)
6459                         Con_Printf("loading cubemap \"%s\"\n", basename);
6460
6461                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6462                 Mem_Free(cubemappixels);
6463         }
6464         else
6465         {
6466                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6467                 if (developer_loading.integer)
6468                 {
6469                         Con_Printf("(tried tried images ");
6470                         for (j = 0;j < 3;j++)
6471                                 for (i = 0;i < 6;i++)
6472                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6473                         Con_Print(" and was unable to find any of them).\n");
6474                 }
6475         }
6476         return cubemaptexture;
6477 }
6478
6479 rtexture_t *R_GetCubemap(const char *basename)
6480 {
6481         int i;
6482         for (i = 0;i < r_texture_numcubemaps;i++)
6483                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6484                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6485         if (i >= MAX_CUBEMAPS)
6486                 return r_texture_whitecube;
6487         r_texture_numcubemaps++;
6488         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6489         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6490         return r_texture_cubemaps[i].texture;
6491 }
6492
6493 void R_FreeCubemaps(void)
6494 {
6495         int i;
6496         for (i = 0;i < r_texture_numcubemaps;i++)
6497         {
6498                 if (developer_loading.integer)
6499                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6500                 if (r_texture_cubemaps[i].texture)
6501                         R_FreeTexture(r_texture_cubemaps[i].texture);
6502         }
6503         r_texture_numcubemaps = 0;
6504 }
6505
6506 void R_Main_FreeViewCache(void)
6507 {
6508         if (r_refdef.viewcache.entityvisible)
6509                 Mem_Free(r_refdef.viewcache.entityvisible);
6510         if (r_refdef.viewcache.world_pvsbits)
6511                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6512         if (r_refdef.viewcache.world_leafvisible)
6513                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6514         if (r_refdef.viewcache.world_surfacevisible)
6515                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6516         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6517 }
6518
6519 void R_Main_ResizeViewCache(void)
6520 {
6521         int numentities = r_refdef.scene.numentities;
6522         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6523         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6524         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6525         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6526         if (r_refdef.viewcache.maxentities < numentities)
6527         {
6528                 r_refdef.viewcache.maxentities = numentities;
6529                 if (r_refdef.viewcache.entityvisible)
6530                         Mem_Free(r_refdef.viewcache.entityvisible);
6531                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6532         }
6533         if (r_refdef.viewcache.world_numclusters != numclusters)
6534         {
6535                 r_refdef.viewcache.world_numclusters = numclusters;
6536                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6537                 if (r_refdef.viewcache.world_pvsbits)
6538                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6539                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6540         }
6541         if (r_refdef.viewcache.world_numleafs != numleafs)
6542         {
6543                 r_refdef.viewcache.world_numleafs = numleafs;
6544                 if (r_refdef.viewcache.world_leafvisible)
6545                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6546                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6547         }
6548         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6549         {
6550                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6551                 if (r_refdef.viewcache.world_surfacevisible)
6552                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6553                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6554         }
6555 }
6556
6557 extern rtexture_t *loadingscreentexture;
6558 void gl_main_start(void)
6559 {
6560         loadingscreentexture = NULL;
6561         r_texture_blanknormalmap = NULL;
6562         r_texture_white = NULL;
6563         r_texture_grey128 = NULL;
6564         r_texture_black = NULL;
6565         r_texture_whitecube = NULL;
6566         r_texture_normalizationcube = NULL;
6567         r_texture_fogattenuation = NULL;
6568         r_texture_fogheighttexture = NULL;
6569         r_texture_gammaramps = NULL;
6570         r_texture_numcubemaps = 0;
6571
6572         r_loaddds = r_texture_dds_load.integer != 0;
6573         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6574
6575         switch(vid.renderpath)
6576         {
6577         case RENDERPATH_GL20:
6578         case RENDERPATH_D3D9:
6579         case RENDERPATH_D3D10:
6580         case RENDERPATH_D3D11:
6581         case RENDERPATH_SOFT:
6582                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6583                 Cvar_SetValueQuick(&gl_combine, 1);
6584                 Cvar_SetValueQuick(&r_glsl, 1);
6585                 r_loadnormalmap = true;
6586                 r_loadgloss = true;
6587                 r_loadfog = false;
6588                 break;
6589         case RENDERPATH_GL13:
6590                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6591                 Cvar_SetValueQuick(&gl_combine, 1);
6592                 Cvar_SetValueQuick(&r_glsl, 0);
6593                 r_loadnormalmap = false;
6594                 r_loadgloss = false;
6595                 r_loadfog = true;
6596                 break;
6597         case RENDERPATH_GL11:
6598                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6599                 Cvar_SetValueQuick(&gl_combine, 0);
6600                 Cvar_SetValueQuick(&r_glsl, 0);
6601                 r_loadnormalmap = false;
6602                 r_loadgloss = false;
6603                 r_loadfog = true;
6604                 break;
6605         case RENDERPATH_GLES2:
6606                 Cvar_SetValueQuick(&r_textureunits, 1);
6607                 Cvar_SetValueQuick(&gl_combine, 1);
6608                 Cvar_SetValueQuick(&r_glsl, 1);
6609                 r_loadnormalmap = true;
6610                 r_loadgloss = false;
6611                 r_loadfog = false;
6612                 break;
6613         }
6614
6615         R_AnimCache_Free();
6616         R_FrameData_Reset();
6617
6618         r_numqueries = 0;
6619         r_maxqueries = 0;
6620         memset(r_queries, 0, sizeof(r_queries));
6621
6622         r_qwskincache = NULL;
6623         r_qwskincache_size = 0;
6624
6625         // set up r_skinframe loading system for textures
6626         memset(&r_skinframe, 0, sizeof(r_skinframe));
6627         r_skinframe.loadsequence = 1;
6628         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6629
6630         r_main_texturepool = R_AllocTexturePool();
6631         R_BuildBlankTextures();
6632         R_BuildNoTexture();
6633         if (vid.support.arb_texture_cube_map)
6634         {
6635                 R_BuildWhiteCube();
6636                 R_BuildNormalizationCube();
6637         }
6638         r_texture_fogattenuation = NULL;
6639         r_texture_fogheighttexture = NULL;
6640         r_texture_gammaramps = NULL;
6641         //r_texture_fogintensity = NULL;
6642         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6643         memset(&r_waterstate, 0, sizeof(r_waterstate));
6644         r_glsl_permutation = NULL;
6645         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6646         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6647         glslshaderstring = NULL;
6648 #ifdef SUPPORTD3D
6649         r_hlsl_permutation = NULL;
6650         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6651         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6652 #endif
6653         hlslshaderstring = NULL;
6654         memset(&r_svbsp, 0, sizeof (r_svbsp));
6655
6656         r_refdef.fogmasktable_density = 0;
6657 }
6658
6659 void gl_main_shutdown(void)
6660 {
6661         R_AnimCache_Free();
6662         R_FrameData_Reset();
6663
6664         R_Main_FreeViewCache();
6665
6666         switch(vid.renderpath)
6667         {
6668         case RENDERPATH_GL11:
6669         case RENDERPATH_GL13:
6670         case RENDERPATH_GL20:
6671         case RENDERPATH_GLES2:
6672                 if (r_maxqueries)
6673                         qglDeleteQueriesARB(r_maxqueries, r_queries);
6674                 break;
6675         case RENDERPATH_D3D9:
6676                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6677                 break;
6678         case RENDERPATH_D3D10:
6679                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6680                 break;
6681         case RENDERPATH_D3D11:
6682                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6683                 break;
6684         case RENDERPATH_SOFT:
6685                 break;
6686         }
6687
6688         r_numqueries = 0;
6689         r_maxqueries = 0;
6690         memset(r_queries, 0, sizeof(r_queries));
6691
6692         r_qwskincache = NULL;
6693         r_qwskincache_size = 0;
6694
6695         // clear out the r_skinframe state
6696         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6697         memset(&r_skinframe, 0, sizeof(r_skinframe));
6698
6699         if (r_svbsp.nodes)
6700                 Mem_Free(r_svbsp.nodes);
6701         memset(&r_svbsp, 0, sizeof (r_svbsp));
6702         R_FreeTexturePool(&r_main_texturepool);
6703         loadingscreentexture = NULL;
6704         r_texture_blanknormalmap = NULL;
6705         r_texture_white = NULL;
6706         r_texture_grey128 = NULL;
6707         r_texture_black = NULL;
6708         r_texture_whitecube = NULL;
6709         r_texture_normalizationcube = NULL;
6710         r_texture_fogattenuation = NULL;
6711         r_texture_fogheighttexture = NULL;
6712         r_texture_gammaramps = NULL;
6713         r_texture_numcubemaps = 0;
6714         //r_texture_fogintensity = NULL;
6715         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6716         memset(&r_waterstate, 0, sizeof(r_waterstate));
6717         R_GLSL_Restart_f();
6718
6719         r_glsl_permutation = NULL;
6720         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6721         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
6722         glslshaderstring = NULL;
6723 #ifdef SUPPORTD3D
6724         r_hlsl_permutation = NULL;
6725         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6726         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
6727 #endif
6728         hlslshaderstring = NULL;
6729 }
6730
6731 extern void CL_ParseEntityLump(char *entitystring);
6732 void gl_main_newmap(void)
6733 {
6734         // FIXME: move this code to client
6735         char *entities, entname[MAX_QPATH];
6736         if (r_qwskincache)
6737                 Mem_Free(r_qwskincache);
6738         r_qwskincache = NULL;
6739         r_qwskincache_size = 0;
6740         if (cl.worldmodel)
6741         {
6742                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6743                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6744                 {
6745                         CL_ParseEntityLump(entities);
6746                         Mem_Free(entities);
6747                         return;
6748                 }
6749                 if (cl.worldmodel->brush.entities)
6750                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6751         }
6752         R_Main_FreeViewCache();
6753
6754         R_FrameData_Reset();
6755 }
6756
6757 void GL_Main_Init(void)
6758 {
6759         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6760
6761         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6762         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6763         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6764         if (gamemode == GAME_NEHAHRA)
6765         {
6766                 Cvar_RegisterVariable (&gl_fogenable);
6767                 Cvar_RegisterVariable (&gl_fogdensity);
6768                 Cvar_RegisterVariable (&gl_fogred);
6769                 Cvar_RegisterVariable (&gl_foggreen);
6770                 Cvar_RegisterVariable (&gl_fogblue);
6771                 Cvar_RegisterVariable (&gl_fogstart);
6772                 Cvar_RegisterVariable (&gl_fogend);
6773                 Cvar_RegisterVariable (&gl_skyclip);
6774         }
6775         Cvar_RegisterVariable(&r_motionblur);
6776         Cvar_RegisterVariable(&r_motionblur_maxblur);
6777         Cvar_RegisterVariable(&r_motionblur_bmin);
6778         Cvar_RegisterVariable(&r_motionblur_vmin);
6779         Cvar_RegisterVariable(&r_motionblur_vmax);
6780         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6781         Cvar_RegisterVariable(&r_motionblur_randomize);
6782         Cvar_RegisterVariable(&r_damageblur);
6783         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6784         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6785         Cvar_RegisterVariable(&r_equalize_entities_by);
6786         Cvar_RegisterVariable(&r_equalize_entities_to);
6787         Cvar_RegisterVariable(&r_depthfirst);
6788         Cvar_RegisterVariable(&r_useinfinitefarclip);
6789         Cvar_RegisterVariable(&r_farclip_base);
6790         Cvar_RegisterVariable(&r_farclip_world);
6791         Cvar_RegisterVariable(&r_nearclip);
6792         Cvar_RegisterVariable(&r_showbboxes);
6793         Cvar_RegisterVariable(&r_showsurfaces);
6794         Cvar_RegisterVariable(&r_showtris);
6795         Cvar_RegisterVariable(&r_shownormals);
6796         Cvar_RegisterVariable(&r_showlighting);
6797         Cvar_RegisterVariable(&r_showshadowvolumes);
6798         Cvar_RegisterVariable(&r_showcollisionbrushes);
6799         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6800         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6801         Cvar_RegisterVariable(&r_showdisabledepthtest);
6802         Cvar_RegisterVariable(&r_drawportals);
6803         Cvar_RegisterVariable(&r_drawentities);
6804         Cvar_RegisterVariable(&r_draw2d);
6805         Cvar_RegisterVariable(&r_drawworld);
6806         Cvar_RegisterVariable(&r_cullentities_trace);
6807         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6808         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6809         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6810         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6811         Cvar_RegisterVariable(&r_drawviewmodel);
6812         Cvar_RegisterVariable(&r_drawexteriormodel);
6813         Cvar_RegisterVariable(&r_speeds);
6814         Cvar_RegisterVariable(&r_fullbrights);
6815         Cvar_RegisterVariable(&r_wateralpha);
6816         Cvar_RegisterVariable(&r_dynamic);
6817         Cvar_RegisterVariable(&r_fakelight);
6818         Cvar_RegisterVariable(&r_fakelight_intensity);
6819         Cvar_RegisterVariable(&r_fullbright);
6820         Cvar_RegisterVariable(&r_shadows);
6821         Cvar_RegisterVariable(&r_shadows_darken);
6822         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6823         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6824         Cvar_RegisterVariable(&r_shadows_throwdistance);
6825         Cvar_RegisterVariable(&r_shadows_throwdirection);
6826         Cvar_RegisterVariable(&r_shadows_focus);
6827         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6828         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6829         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6830         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6831         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6832         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6833         Cvar_RegisterVariable(&r_fog_exp2);
6834         Cvar_RegisterVariable(&r_drawfog);
6835         Cvar_RegisterVariable(&r_transparentdepthmasking);
6836         Cvar_RegisterVariable(&r_texture_dds_load);
6837         Cvar_RegisterVariable(&r_texture_dds_save);
6838         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6839         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6840         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6841         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6842         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6843         Cvar_RegisterVariable(&r_textureunits);
6844         Cvar_RegisterVariable(&gl_combine);
6845         Cvar_RegisterVariable(&r_glsl);
6846         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6847         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6848         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6849         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6850         Cvar_RegisterVariable(&r_glsl_postprocess);
6851         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6852         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6853         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6854         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6855         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6856         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6857         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6858         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6859
6860         Cvar_RegisterVariable(&r_water);
6861         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6862         Cvar_RegisterVariable(&r_water_clippingplanebias);
6863         Cvar_RegisterVariable(&r_water_refractdistort);
6864         Cvar_RegisterVariable(&r_water_reflectdistort);
6865         Cvar_RegisterVariable(&r_water_scissormode);
6866         Cvar_RegisterVariable(&r_lerpsprites);
6867         Cvar_RegisterVariable(&r_lerpmodels);
6868         Cvar_RegisterVariable(&r_lerplightstyles);
6869         Cvar_RegisterVariable(&r_waterscroll);
6870         Cvar_RegisterVariable(&r_bloom);
6871         Cvar_RegisterVariable(&r_bloom_colorscale);
6872         Cvar_RegisterVariable(&r_bloom_brighten);
6873         Cvar_RegisterVariable(&r_bloom_blur);
6874         Cvar_RegisterVariable(&r_bloom_resolution);
6875         Cvar_RegisterVariable(&r_bloom_colorexponent);
6876         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6877         Cvar_RegisterVariable(&r_hdr);
6878         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6879         Cvar_RegisterVariable(&r_hdr_glowintensity);
6880         Cvar_RegisterVariable(&r_hdr_range);
6881         Cvar_RegisterVariable(&r_hdr_irisadaptation);
6882         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
6883         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
6884         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
6885         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
6886         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
6887         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6888         Cvar_RegisterVariable(&developer_texturelogging);
6889         Cvar_RegisterVariable(&gl_lightmaps);
6890         Cvar_RegisterVariable(&r_test);
6891         Cvar_RegisterVariable(&r_glsl_saturation);
6892         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6893         Cvar_RegisterVariable(&r_framedatasize);
6894         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6895                 Cvar_SetValue("r_fullbrights", 0);
6896         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6897
6898         Cvar_RegisterVariable(&r_track_sprites);
6899         Cvar_RegisterVariable(&r_track_sprites_flags);
6900         Cvar_RegisterVariable(&r_track_sprites_scalew);
6901         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6902         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6903         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6904         Cvar_RegisterVariable(&r_overheadsprites_scalex);
6905         Cvar_RegisterVariable(&r_overheadsprites_scaley);
6906 }
6907
6908 extern void R_Textures_Init(void);
6909 extern void GL_Draw_Init(void);
6910 extern void GL_Main_Init(void);
6911 extern void R_Shadow_Init(void);
6912 extern void R_Sky_Init(void);
6913 extern void GL_Surf_Init(void);
6914 extern void R_Particles_Init(void);
6915 extern void R_Explosion_Init(void);
6916 extern void gl_backend_init(void);
6917 extern void Sbar_Init(void);
6918 extern void R_LightningBeams_Init(void);
6919 extern void Mod_RenderInit(void);
6920 extern void Font_Init(void);
6921
6922 void Render_Init(void)
6923 {
6924         gl_backend_init();
6925         R_Textures_Init();
6926         GL_Main_Init();
6927         Font_Init();
6928         GL_Draw_Init();
6929         R_Shadow_Init();
6930         R_Sky_Init();
6931         GL_Surf_Init();
6932         Sbar_Init();
6933         R_Particles_Init();
6934         R_Explosion_Init();
6935         R_LightningBeams_Init();
6936         Mod_RenderInit();
6937 }
6938
6939 /*
6940 ===============
6941 GL_Init
6942 ===============
6943 */
6944 extern char *ENGINE_EXTENSIONS;
6945 void GL_Init (void)
6946 {
6947         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6948         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6949         gl_version = (const char *)qglGetString(GL_VERSION);
6950         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6951
6952         if (!gl_extensions)
6953                 gl_extensions = "";
6954         if (!gl_platformextensions)
6955                 gl_platformextensions = "";
6956
6957         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6958         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6959         Con_Printf("GL_VERSION: %s\n", gl_version);
6960         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6961         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6962
6963         VID_CheckExtensions();
6964
6965         // LordHavoc: report supported extensions
6966         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6967
6968         // clear to black (loading plaque will be seen over this)
6969         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6970 }
6971
6972 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6973 {
6974         int i;
6975         mplane_t *p;
6976         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6977         {
6978                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6979                 if (i == 4)
6980                         continue;
6981                 p = r_refdef.view.frustum + i;
6982                 switch(p->signbits)
6983                 {
6984                 default:
6985                 case 0:
6986                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6987                                 return true;
6988                         break;
6989                 case 1:
6990                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6991                                 return true;
6992                         break;
6993                 case 2:
6994                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6995                                 return true;
6996                         break;
6997                 case 3:
6998                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6999                                 return true;
7000                         break;
7001                 case 4:
7002                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7003                                 return true;
7004                         break;
7005                 case 5:
7006                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7007                                 return true;
7008                         break;
7009                 case 6:
7010                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7011                                 return true;
7012                         break;
7013                 case 7:
7014                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7015                                 return true;
7016                         break;
7017                 }
7018         }
7019         return false;
7020 }
7021
7022 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7023 {
7024         int i;
7025         const mplane_t *p;
7026         for (i = 0;i < numplanes;i++)
7027         {
7028                 p = planes + i;
7029                 switch(p->signbits)
7030                 {
7031                 default:
7032                 case 0:
7033                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7034                                 return true;
7035                         break;
7036                 case 1:
7037                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7038                                 return true;
7039                         break;
7040                 case 2:
7041                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7042                                 return true;
7043                         break;
7044                 case 3:
7045                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7046                                 return true;
7047                         break;
7048                 case 4:
7049                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7050                                 return true;
7051                         break;
7052                 case 5:
7053                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7054                                 return true;
7055                         break;
7056                 case 6:
7057                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7058                                 return true;
7059                         break;
7060                 case 7:
7061                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7062                                 return true;
7063                         break;
7064                 }
7065         }
7066         return false;
7067 }
7068
7069 //==================================================================================
7070
7071 // LordHavoc: this stores temporary data used within the same frame
7072
7073 typedef struct r_framedata_mem_s
7074 {
7075         struct r_framedata_mem_s *purge; // older mem block to free on next frame
7076         size_t size; // how much usable space
7077         size_t current; // how much space in use
7078         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7079         size_t wantedsize; // how much space was allocated
7080         unsigned char *data; // start of real data (16byte aligned)
7081 }
7082 r_framedata_mem_t;
7083
7084 static r_framedata_mem_t *r_framedata_mem;
7085
7086 void R_FrameData_Reset(void)
7087 {
7088         while (r_framedata_mem)
7089         {
7090                 r_framedata_mem_t *next = r_framedata_mem->purge;
7091                 Mem_Free(r_framedata_mem);
7092                 r_framedata_mem = next;
7093         }
7094 }
7095
7096 void R_FrameData_Resize(void)
7097 {
7098         size_t wantedsize;
7099         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7100         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7101         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7102         {
7103                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7104                 newmem->wantedsize = wantedsize;
7105                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7106                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7107                 newmem->current = 0;
7108                 newmem->mark = 0;
7109                 newmem->purge = r_framedata_mem;
7110                 r_framedata_mem = newmem;
7111         }
7112 }
7113
7114 void R_FrameData_NewFrame(void)
7115 {
7116         R_FrameData_Resize();
7117         if (!r_framedata_mem)
7118                 return;
7119         // if we ran out of space on the last frame, free the old memory now
7120         while (r_framedata_mem->purge)
7121         {
7122                 // repeatedly remove the second item in the list, leaving only head
7123                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7124                 Mem_Free(r_framedata_mem->purge);
7125                 r_framedata_mem->purge = next;
7126         }
7127         // reset the current mem pointer
7128         r_framedata_mem->current = 0;
7129         r_framedata_mem->mark = 0;
7130 }
7131
7132 void *R_FrameData_Alloc(size_t size)
7133 {
7134         void *data;
7135
7136         // align to 16 byte boundary - the data pointer is already aligned, so we
7137         // only need to ensure the size of every allocation is also aligned
7138         size = (size + 15) & ~15;
7139
7140         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7141         {
7142                 // emergency - we ran out of space, allocate more memory
7143                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7144                 R_FrameData_Resize();
7145         }
7146
7147         data = r_framedata_mem->data + r_framedata_mem->current;
7148         r_framedata_mem->current += size;
7149
7150         // count the usage for stats
7151         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7152         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7153
7154         return (void *)data;
7155 }
7156
7157 void *R_FrameData_Store(size_t size, void *data)
7158 {
7159         void *d = R_FrameData_Alloc(size);
7160         if (d && data)
7161                 memcpy(d, data, size);
7162         return d;
7163 }
7164
7165 void R_FrameData_SetMark(void)
7166 {
7167         if (!r_framedata_mem)
7168                 return;
7169         r_framedata_mem->mark = r_framedata_mem->current;
7170 }
7171
7172 void R_FrameData_ReturnToMark(void)
7173 {
7174         if (!r_framedata_mem)
7175                 return;
7176         r_framedata_mem->current = r_framedata_mem->mark;
7177 }
7178
7179 //==================================================================================
7180
7181 // LordHavoc: animcache originally written by Echon, rewritten since then
7182
7183 /**
7184  * Animation cache prevents re-generating mesh data for an animated model
7185  * multiple times in one frame for lighting, shadowing, reflections, etc.
7186  */
7187
7188 void R_AnimCache_Free(void)
7189 {
7190 }
7191
7192 void R_AnimCache_ClearCache(void)
7193 {
7194         int i;
7195         entity_render_t *ent;
7196
7197         for (i = 0;i < r_refdef.scene.numentities;i++)
7198         {
7199                 ent = r_refdef.scene.entities[i];
7200                 ent->animcache_vertex3f = NULL;
7201                 ent->animcache_normal3f = NULL;
7202                 ent->animcache_svector3f = NULL;
7203                 ent->animcache_tvector3f = NULL;
7204                 ent->animcache_vertexmesh = NULL;
7205                 ent->animcache_vertex3fbuffer = NULL;
7206                 ent->animcache_vertexmeshbuffer = NULL;
7207         }
7208 }
7209
7210 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7211 {
7212         int i;
7213
7214         // check if we need the meshbuffers
7215         if (!vid.useinterleavedarrays)
7216                 return;
7217
7218         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7219                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7220         // TODO: upload vertex3f buffer?
7221         if (ent->animcache_vertexmesh)
7222         {
7223                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7224                 for (i = 0;i < numvertices;i++)
7225                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7226                 if (ent->animcache_svector3f)
7227                         for (i = 0;i < numvertices;i++)
7228                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7229                 if (ent->animcache_tvector3f)
7230                         for (i = 0;i < numvertices;i++)
7231                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7232                 if (ent->animcache_normal3f)
7233                         for (i = 0;i < numvertices;i++)
7234                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7235                 // TODO: upload vertexmeshbuffer?
7236         }
7237 }
7238
7239 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7240 {
7241         dp_model_t *model = ent->model;
7242         int numvertices;
7243         // see if it's already cached this frame
7244         if (ent->animcache_vertex3f)
7245         {
7246                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7247                 if (wantnormals || wanttangents)
7248                 {
7249                         if (ent->animcache_normal3f)
7250                                 wantnormals = false;
7251                         if (ent->animcache_svector3f)
7252                                 wanttangents = false;
7253                         if (wantnormals || wanttangents)
7254                         {
7255                                 numvertices = model->surfmesh.num_vertices;
7256                                 if (wantnormals)
7257                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7258                                 if (wanttangents)
7259                                 {
7260                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7261                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7262                                 }
7263                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7264                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7265                         }
7266                 }
7267         }
7268         else
7269         {
7270                 // see if this ent is worth caching
7271                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7272                         return false;
7273                 // get some memory for this entity and generate mesh data
7274                 numvertices = model->surfmesh.num_vertices;
7275                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7276                 if (wantnormals)
7277                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7278                 if (wanttangents)
7279                 {
7280                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7281                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7282                 }
7283                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7284                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7285         }
7286         return true;
7287 }
7288
7289 void R_AnimCache_CacheVisibleEntities(void)
7290 {
7291         int i;
7292         qboolean wantnormals = true;
7293         qboolean wanttangents = !r_showsurfaces.integer;
7294
7295         switch(vid.renderpath)
7296         {
7297         case RENDERPATH_GL20:
7298         case RENDERPATH_D3D9:
7299         case RENDERPATH_D3D10:
7300         case RENDERPATH_D3D11:
7301         case RENDERPATH_GLES2:
7302                 break;
7303         case RENDERPATH_GL13:
7304         case RENDERPATH_GL11:
7305                 wanttangents = false;
7306                 break;
7307         case RENDERPATH_SOFT:
7308                 break;
7309         }
7310
7311         if (r_shownormals.integer)
7312                 wanttangents = wantnormals = true;
7313
7314         // TODO: thread this
7315         // NOTE: R_PrepareRTLights() also caches entities
7316
7317         for (i = 0;i < r_refdef.scene.numentities;i++)
7318                 if (r_refdef.viewcache.entityvisible[i])
7319                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7320 }
7321
7322 //==================================================================================
7323
7324 static void R_View_UpdateEntityLighting (void)
7325 {
7326         int i;
7327         entity_render_t *ent;
7328         vec3_t tempdiffusenormal, avg;
7329         vec_t f, fa, fd, fdd;
7330         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7331
7332         for (i = 0;i < r_refdef.scene.numentities;i++)
7333         {
7334                 ent = r_refdef.scene.entities[i];
7335
7336                 // skip unseen models
7337                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7338                         continue;
7339
7340                 // skip bsp models
7341                 if (ent->model && ent->model->brush.num_leafs)
7342                 {
7343                         // TODO: use modellight for r_ambient settings on world?
7344                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7345                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7346                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7347                         continue;
7348                 }
7349
7350                 // fetch the lighting from the worldmodel data
7351                 VectorClear(ent->modellight_ambient);
7352                 VectorClear(ent->modellight_diffuse);
7353                 VectorClear(tempdiffusenormal);
7354                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7355                 {
7356                         vec3_t org;
7357                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7358
7359                         // complete lightning for lit sprites
7360                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7361                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7362                         {
7363                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7364                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7365                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7366                         }
7367                         else
7368                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
7369
7370                         if(ent->flags & RENDER_EQUALIZE)
7371                         {
7372                                 // first fix up ambient lighting...
7373                                 if(r_equalize_entities_minambient.value > 0)
7374                                 {
7375                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7376                                         if(fd > 0)
7377                                         {
7378                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7379                                                 if(fa < r_equalize_entities_minambient.value * fd)
7380                                                 {
7381                                                         // solve:
7382                                                         //   fa'/fd' = minambient
7383                                                         //   fa'+0.25*fd' = fa+0.25*fd
7384                                                         //   ...
7385                                                         //   fa' = fd' * minambient
7386                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7387                                                         //   ...
7388                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7389                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7390                                                         //   ...
7391                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7392                                                         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
7393                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7394                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7395                                                 }
7396                                         }
7397                                 }
7398
7399                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7400                                 {
7401                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7402                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7403                                         f = fa + 0.25 * fd;
7404                                         if(f > 0)
7405                                         {
7406                                                 // adjust brightness and saturation to target
7407                                                 avg[0] = avg[1] = avg[2] = fa / f;
7408                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7409                                                 avg[0] = avg[1] = avg[2] = fd / f;
7410                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7411                                         }
7412                                 }
7413                         }
7414                 }
7415                 else // highly rare
7416                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7417
7418                 // move the light direction into modelspace coordinates for lighting code
7419                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7420                 if(VectorLength2(ent->modellight_lightdir) == 0)
7421                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7422                 VectorNormalize(ent->modellight_lightdir);
7423         }
7424 }
7425
7426 #define MAX_LINEOFSIGHTTRACES 64
7427
7428 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7429 {
7430         int i;
7431         vec3_t boxmins, boxmaxs;
7432         vec3_t start;
7433         vec3_t end;
7434         dp_model_t *model = r_refdef.scene.worldmodel;
7435
7436         if (!model || !model->brush.TraceLineOfSight)
7437                 return true;
7438
7439         // expand the box a little
7440         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7441         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7442         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7443         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7444         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7445         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7446
7447         // return true if eye is inside enlarged box
7448         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7449                 return true;
7450
7451         // try center
7452         VectorCopy(eye, start);
7453         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7454         if (model->brush.TraceLineOfSight(model, start, end))
7455                 return true;
7456
7457         // try various random positions
7458         for (i = 0;i < numsamples;i++)
7459         {
7460                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7461                 if (model->brush.TraceLineOfSight(model, start, end))
7462                         return true;
7463         }
7464
7465         return false;
7466 }
7467
7468
7469 static void R_View_UpdateEntityVisible (void)
7470 {
7471         int i;
7472         int renderimask;
7473         int samples;
7474         entity_render_t *ent;
7475
7476         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7477                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7478                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7479                 :                                                          RENDER_EXTERIORMODEL;
7480         if (!r_drawviewmodel.integer)
7481                 renderimask |= RENDER_VIEWMODEL;
7482         if (!r_drawexteriormodel.integer)
7483                 renderimask |= RENDER_EXTERIORMODEL;
7484         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7485         {
7486                 // worldmodel can check visibility
7487                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7488                 for (i = 0;i < r_refdef.scene.numentities;i++)
7489                 {
7490                         ent = r_refdef.scene.entities[i];
7491                         if (!(ent->flags & renderimask))
7492                         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)))
7493                         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))
7494                                 r_refdef.viewcache.entityvisible[i] = true;
7495                 }
7496                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7497                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7498                 {
7499                         for (i = 0;i < r_refdef.scene.numentities;i++)
7500                         {
7501                                 ent = r_refdef.scene.entities[i];
7502                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7503                                 {
7504                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7505                                         if (samples < 0)
7506                                                 continue; // temp entities do pvs only
7507                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7508                                                 ent->last_trace_visibility = realtime;
7509                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7510                                                 r_refdef.viewcache.entityvisible[i] = 0;
7511                                 }
7512                         }
7513                 }
7514         }
7515         else
7516         {
7517                 // no worldmodel or it can't check visibility
7518                 for (i = 0;i < r_refdef.scene.numentities;i++)
7519                 {
7520                         ent = r_refdef.scene.entities[i];
7521                         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));
7522                 }
7523         }
7524 }
7525
7526 /// only used if skyrendermasked, and normally returns false
7527 int R_DrawBrushModelsSky (void)
7528 {
7529         int i, sky;
7530         entity_render_t *ent;
7531
7532         sky = false;
7533         for (i = 0;i < r_refdef.scene.numentities;i++)
7534         {
7535                 if (!r_refdef.viewcache.entityvisible[i])
7536                         continue;
7537                 ent = r_refdef.scene.entities[i];
7538                 if (!ent->model || !ent->model->DrawSky)
7539                         continue;
7540                 ent->model->DrawSky(ent);
7541                 sky = true;
7542         }
7543         return sky;
7544 }
7545
7546 static void R_DrawNoModel(entity_render_t *ent);
7547 static void R_DrawModels(void)
7548 {
7549         int i;
7550         entity_render_t *ent;
7551
7552         for (i = 0;i < r_refdef.scene.numentities;i++)
7553         {
7554                 if (!r_refdef.viewcache.entityvisible[i])
7555                         continue;
7556                 ent = r_refdef.scene.entities[i];
7557                 r_refdef.stats.entities++;
7558                 if (ent->model && ent->model->Draw != NULL)
7559                         ent->model->Draw(ent);
7560                 else
7561                         R_DrawNoModel(ent);
7562         }
7563 }
7564
7565 static void R_DrawModelsDepth(void)
7566 {
7567         int i;
7568         entity_render_t *ent;
7569
7570         for (i = 0;i < r_refdef.scene.numentities;i++)
7571         {
7572                 if (!r_refdef.viewcache.entityvisible[i])
7573                         continue;
7574                 ent = r_refdef.scene.entities[i];
7575                 if (ent->model && ent->model->DrawDepth != NULL)
7576                         ent->model->DrawDepth(ent);
7577         }
7578 }
7579
7580 static void R_DrawModelsDebug(void)
7581 {
7582         int i;
7583         entity_render_t *ent;
7584
7585         for (i = 0;i < r_refdef.scene.numentities;i++)
7586         {
7587                 if (!r_refdef.viewcache.entityvisible[i])
7588                         continue;
7589                 ent = r_refdef.scene.entities[i];
7590                 if (ent->model && ent->model->DrawDebug != NULL)
7591                         ent->model->DrawDebug(ent);
7592         }
7593 }
7594
7595 static void R_DrawModelsAddWaterPlanes(void)
7596 {
7597         int i;
7598         entity_render_t *ent;
7599
7600         for (i = 0;i < r_refdef.scene.numentities;i++)
7601         {
7602                 if (!r_refdef.viewcache.entityvisible[i])
7603                         continue;
7604                 ent = r_refdef.scene.entities[i];
7605                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7606                         ent->model->DrawAddWaterPlanes(ent);
7607         }
7608 }
7609
7610 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
7611 {
7612         if (r_hdr_irisadaptation.integer)
7613         {
7614                 vec3_t ambient;
7615                 vec3_t diffuse;
7616                 vec3_t diffusenormal;
7617                 vec_t brightness;
7618                 vec_t goal;
7619                 vec_t adjust;
7620                 vec_t current;
7621                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7622                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
7623                 brightness = max(0.0000001f, brightness);
7624                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
7625                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
7626                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
7627                 current = r_hdr_irisadaptation_value.value;
7628                 if (current < goal)
7629                         current = min(current + adjust, goal);
7630                 else if (current > goal)
7631                         current = max(current - adjust, goal);
7632                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
7633                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
7634         }
7635         else if (r_hdr_irisadaptation_value.value != 1.0f)
7636                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
7637 }
7638
7639 static void R_View_SetFrustum(const int *scissor)
7640 {
7641         int i;
7642         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7643         vec3_t forward, left, up, origin, v;
7644
7645         if(scissor)
7646         {
7647                 // flipped x coordinates (because x points left here)
7648                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7649                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7650
7651                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
7652                 switch(vid.renderpath)
7653                 {
7654                         case RENDERPATH_D3D9:
7655                         case RENDERPATH_D3D10:
7656                         case RENDERPATH_D3D11:
7657                         case RENDERPATH_SOFT:
7658                                 // non-flipped y coordinates
7659                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7660                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7661                                 break;
7662                         case RENDERPATH_GL11:
7663                         case RENDERPATH_GL13:
7664                         case RENDERPATH_GL20:
7665                         case RENDERPATH_GLES2:
7666                                 // non-flipped y coordinates
7667                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7668                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7669                                 break;
7670                 }
7671         }
7672
7673         // we can't trust r_refdef.view.forward and friends in reflected scenes
7674         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7675
7676 #if 0
7677         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7678         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7679         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7680         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7681         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7682         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7683         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7684         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7685         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7686         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7687         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7688         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7689 #endif
7690
7691 #if 0
7692         zNear = r_refdef.nearclip;
7693         nudge = 1.0 - 1.0 / (1<<23);
7694         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7695         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7696         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7697         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7698         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7699         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7700         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7701         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7702 #endif
7703
7704
7705
7706 #if 0
7707         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7708         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7709         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7710         r_refdef.view.frustum[0].dist = m[15] - m[12];
7711
7712         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7713         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7714         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7715         r_refdef.view.frustum[1].dist = m[15] + m[12];
7716
7717         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7718         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7719         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7720         r_refdef.view.frustum[2].dist = m[15] - m[13];
7721
7722         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7723         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7724         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7725         r_refdef.view.frustum[3].dist = m[15] + m[13];
7726
7727         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7728         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7729         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7730         r_refdef.view.frustum[4].dist = m[15] - m[14];
7731
7732         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7733         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7734         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7735         r_refdef.view.frustum[5].dist = m[15] + m[14];
7736 #endif
7737
7738         if (r_refdef.view.useperspective)
7739         {
7740                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7741                 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]);
7742                 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]);
7743                 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]);
7744                 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]);
7745
7746                 // then the normals from the corners relative to origin
7747                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7748                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7749                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7750                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7751
7752                 // in a NORMAL view, forward cross left == up
7753                 // in a REFLECTED view, forward cross left == down
7754                 // so our cross products above need to be adjusted for a left handed coordinate system
7755                 CrossProduct(forward, left, v);
7756                 if(DotProduct(v, up) < 0)
7757                 {
7758                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7759                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7760                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7761                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7762                 }
7763
7764                 // Leaving those out was a mistake, those were in the old code, and they
7765                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7766                 // I couldn't reproduce it after adding those normalizations. --blub
7767                 VectorNormalize(r_refdef.view.frustum[0].normal);
7768                 VectorNormalize(r_refdef.view.frustum[1].normal);
7769                 VectorNormalize(r_refdef.view.frustum[2].normal);
7770                 VectorNormalize(r_refdef.view.frustum[3].normal);
7771
7772                 // make the corners absolute
7773                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7774                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7775                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7776                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7777
7778                 // one more normal
7779                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7780
7781                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7782                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7783                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7784                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7785                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7786         }
7787         else
7788         {
7789                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7790                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7791                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7792                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7793                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7794                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7795                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7796                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7797                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7798                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7799         }
7800         r_refdef.view.numfrustumplanes = 5;
7801
7802         if (r_refdef.view.useclipplane)
7803         {
7804                 r_refdef.view.numfrustumplanes = 6;
7805                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7806         }
7807
7808         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7809                 PlaneClassify(r_refdef.view.frustum + i);
7810
7811         // LordHavoc: note to all quake engine coders, Quake had a special case
7812         // for 90 degrees which assumed a square view (wrong), so I removed it,
7813         // Quake2 has it disabled as well.
7814
7815         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7816         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7817         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7818         //PlaneClassify(&frustum[0]);
7819
7820         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7821         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7822         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7823         //PlaneClassify(&frustum[1]);
7824
7825         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7826         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7827         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7828         //PlaneClassify(&frustum[2]);
7829
7830         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7831         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7832         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7833         //PlaneClassify(&frustum[3]);
7834
7835         // nearclip plane
7836         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7837         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7838         //PlaneClassify(&frustum[4]);
7839 }
7840
7841 void R_View_UpdateWithScissor(const int *myscissor)
7842 {
7843         R_Main_ResizeViewCache();
7844         R_View_SetFrustum(myscissor);
7845         R_View_WorldVisibility(r_refdef.view.useclipplane);
7846         R_View_UpdateEntityVisible();
7847         R_View_UpdateEntityLighting();
7848 }
7849
7850 void R_View_Update(void)
7851 {
7852         R_Main_ResizeViewCache();
7853         R_View_SetFrustum(NULL);
7854         R_View_WorldVisibility(r_refdef.view.useclipplane);
7855         R_View_UpdateEntityVisible();
7856         R_View_UpdateEntityLighting();
7857 }
7858
7859 void R_SetupView(qboolean allowwaterclippingplane)
7860 {
7861         const float *customclipplane = NULL;
7862         float plane[4];
7863         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7864         {
7865                 // LordHavoc: couldn't figure out how to make this approach the
7866                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7867                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7868                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7869                         dist = r_refdef.view.clipplane.dist;
7870                 plane[0] = r_refdef.view.clipplane.normal[0];
7871                 plane[1] = r_refdef.view.clipplane.normal[1];
7872                 plane[2] = r_refdef.view.clipplane.normal[2];
7873                 plane[3] = dist;
7874                 customclipplane = plane;
7875         }
7876
7877         if (!r_refdef.view.useperspective)
7878                 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);
7879         else if (vid.stencil && r_useinfinitefarclip.integer)
7880                 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);
7881         else
7882                 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);
7883         R_SetViewport(&r_refdef.view.viewport);
7884 }
7885
7886 void R_EntityMatrix(const matrix4x4_t *matrix)
7887 {
7888         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7889         {
7890                 gl_modelmatrixchanged = false;
7891                 gl_modelmatrix = *matrix;
7892                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7893                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7894                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7895                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7896                 CHECKGLERROR
7897                 switch(vid.renderpath)
7898                 {
7899                 case RENDERPATH_D3D9:
7900 #ifdef SUPPORTD3D
7901                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
7902                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
7903 #endif
7904                         break;
7905                 case RENDERPATH_D3D10:
7906                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
7907                         break;
7908                 case RENDERPATH_D3D11:
7909                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
7910                         break;
7911                 case RENDERPATH_GL13:
7912                 case RENDERPATH_GL11:
7913                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7914                         break;
7915                 case RENDERPATH_SOFT:
7916                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
7917                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
7918                         break;
7919                 case RENDERPATH_GL20:
7920                 case RENDERPATH_GLES2:
7921                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7922                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7923                         break;
7924                 }
7925         }
7926 }
7927
7928 void R_ResetViewRendering2D(void)
7929 {
7930         r_viewport_t viewport;
7931         DrawQ_Finish();
7932
7933         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7934         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);
7935         R_SetViewport(&viewport);
7936         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7937         GL_Color(1, 1, 1, 1);
7938         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7939         GL_BlendFunc(GL_ONE, GL_ZERO);
7940         GL_ScissorTest(false);
7941         GL_DepthMask(false);
7942         GL_DepthRange(0, 1);
7943         GL_DepthTest(false);
7944         GL_DepthFunc(GL_LEQUAL);
7945         R_EntityMatrix(&identitymatrix);
7946         R_Mesh_ResetTextureState();
7947         GL_PolygonOffset(0, 0);
7948         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7949         switch(vid.renderpath)
7950         {
7951         case RENDERPATH_GL11:
7952         case RENDERPATH_GL13:
7953         case RENDERPATH_GL20:
7954         case RENDERPATH_GLES2:
7955                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7956                 break;
7957         case RENDERPATH_D3D9:
7958         case RENDERPATH_D3D10:
7959         case RENDERPATH_D3D11:
7960         case RENDERPATH_SOFT:
7961                 break;
7962         }
7963         GL_CullFace(GL_NONE);
7964 }
7965
7966 void R_ResetViewRendering3D(void)
7967 {
7968         DrawQ_Finish();
7969
7970         R_SetupView(true);
7971         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7972         GL_Color(1, 1, 1, 1);
7973         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7974         GL_BlendFunc(GL_ONE, GL_ZERO);
7975         GL_ScissorTest(true);
7976         GL_DepthMask(true);
7977         GL_DepthRange(0, 1);
7978         GL_DepthTest(true);
7979         GL_DepthFunc(GL_LEQUAL);
7980         R_EntityMatrix(&identitymatrix);
7981         R_Mesh_ResetTextureState();
7982         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7983         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7984         switch(vid.renderpath)
7985         {
7986         case RENDERPATH_GL11:
7987         case RENDERPATH_GL13:
7988         case RENDERPATH_GL20:
7989         case RENDERPATH_GLES2:
7990                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7991                 break;
7992         case RENDERPATH_D3D9:
7993         case RENDERPATH_D3D10:
7994         case RENDERPATH_D3D11:
7995         case RENDERPATH_SOFT:
7996                 break;
7997         }
7998         GL_CullFace(r_refdef.view.cullface_back);
7999 }
8000
8001 /*
8002 ================
8003 R_RenderView_UpdateViewVectors
8004 ================
8005 */
8006 static void R_RenderView_UpdateViewVectors(void)
8007 {
8008         // break apart the view matrix into vectors for various purposes
8009         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8010         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8011         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8012         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8013         // make an inverted copy of the view matrix for tracking sprites
8014         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8015 }
8016
8017 void R_RenderScene(void);
8018 void R_RenderWaterPlanes(void);
8019
8020 static void R_Water_StartFrame(void)
8021 {
8022         int i;
8023         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8024         r_waterstate_waterplane_t *p;
8025
8026         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8027                 return;
8028
8029         switch(vid.renderpath)
8030         {
8031         case RENDERPATH_GL20:
8032         case RENDERPATH_D3D9:
8033         case RENDERPATH_D3D10:
8034         case RENDERPATH_D3D11:
8035         case RENDERPATH_SOFT:
8036         case RENDERPATH_GLES2:
8037                 break;
8038         case RENDERPATH_GL13:
8039         case RENDERPATH_GL11:
8040                 return;
8041         }
8042
8043         // set waterwidth and waterheight to the water resolution that will be
8044         // used (often less than the screen resolution for faster rendering)
8045         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8046         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8047
8048         // calculate desired texture sizes
8049         // can't use water if the card does not support the texture size
8050         if (!r_water.integer || r_showsurfaces.integer)
8051                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8052         else if (vid.support.arb_texture_non_power_of_two)
8053         {
8054                 texturewidth = waterwidth;
8055                 textureheight = waterheight;
8056                 camerawidth = waterwidth;
8057                 cameraheight = waterheight;
8058         }
8059         else
8060         {
8061                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8062                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8063                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8064                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8065         }
8066
8067         // allocate textures as needed
8068         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8069         {
8070                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8071                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8072                 {
8073                         if (p->texture_refraction)
8074                                 R_FreeTexture(p->texture_refraction);
8075                         p->texture_refraction = NULL;
8076                         if (p->texture_reflection)
8077                                 R_FreeTexture(p->texture_reflection);
8078                         p->texture_reflection = NULL;
8079                         if (p->texture_camera)
8080                                 R_FreeTexture(p->texture_camera);
8081                         p->texture_camera = NULL;
8082                 }
8083                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8084                 r_waterstate.texturewidth = texturewidth;
8085                 r_waterstate.textureheight = textureheight;
8086                 r_waterstate.camerawidth = camerawidth;
8087                 r_waterstate.cameraheight = cameraheight;
8088         }
8089
8090         if (r_waterstate.texturewidth)
8091         {
8092                 r_waterstate.enabled = true;
8093
8094                 // when doing a reduced render (HDR) we want to use a smaller area
8095                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8096                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8097
8098                 // set up variables that will be used in shader setup
8099                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8100                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8101                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8102                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8103         }
8104
8105         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8106         r_waterstate.numwaterplanes = 0;
8107 }
8108
8109 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8110 {
8111         int triangleindex, planeindex;
8112         const int *e;
8113         vec3_t vert[3];
8114         vec3_t normal;
8115         vec3_t center;
8116         mplane_t plane;
8117         r_waterstate_waterplane_t *p;
8118         texture_t *t = R_GetCurrentTexture(surface->texture);
8119
8120         // just use the first triangle with a valid normal for any decisions
8121         VectorClear(normal);
8122         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8123         {
8124                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8125                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8126                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8127                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8128                 if (VectorLength2(normal) >= 0.001)
8129                         break;
8130         }
8131
8132         VectorCopy(normal, plane.normal);
8133         VectorNormalize(plane.normal);
8134         plane.dist = DotProduct(vert[0], plane.normal);
8135         PlaneClassify(&plane);
8136         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8137         {
8138                 // skip backfaces (except if nocullface is set)
8139                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8140                         return;
8141                 VectorNegate(plane.normal, plane.normal);
8142                 plane.dist *= -1;
8143                 PlaneClassify(&plane);
8144         }
8145
8146
8147         // find a matching plane if there is one
8148         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8149                 if(p->camera_entity == t->camera_entity)
8150                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8151                                 break;
8152         if (planeindex >= r_waterstate.maxwaterplanes)
8153                 return; // nothing we can do, out of planes
8154
8155         // if this triangle does not fit any known plane rendered this frame, add one
8156         if (planeindex >= r_waterstate.numwaterplanes)
8157         {
8158                 // store the new plane
8159                 r_waterstate.numwaterplanes++;
8160                 p->plane = plane;
8161                 // clear materialflags and pvs
8162                 p->materialflags = 0;
8163                 p->pvsvalid = false;
8164                 p->camera_entity = t->camera_entity;
8165                 VectorCopy(surface->mins, p->mins);
8166                 VectorCopy(surface->maxs, p->maxs);
8167         }
8168         else
8169         {
8170                 // merge mins/maxs
8171                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8172                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8173                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8174                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8175                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8176                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8177         }
8178         // merge this surface's materialflags into the waterplane
8179         p->materialflags |= t->currentmaterialflags;
8180         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8181         {
8182                 // merge this surface's PVS into the waterplane
8183                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8184                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8185                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8186                 {
8187                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8188                         p->pvsvalid = true;
8189                 }
8190         }
8191 }
8192
8193 static void R_Water_ProcessPlanes(void)
8194 {
8195         int myscissor[4];
8196         r_refdef_view_t originalview;
8197         r_refdef_view_t myview;
8198         int planeindex;
8199         r_waterstate_waterplane_t *p;
8200         vec3_t visorigin;
8201
8202         originalview = r_refdef.view;
8203
8204         // make sure enough textures are allocated
8205         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8206         {
8207                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8208                 {
8209                         if (!p->texture_refraction)
8210                                 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);
8211                         if (!p->texture_refraction)
8212                                 goto error;
8213                 }
8214                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8215                 {
8216                         if (!p->texture_camera)
8217                                 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);
8218                         if (!p->texture_camera)
8219                                 goto error;
8220                 }
8221
8222                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8223                 {
8224                         if (!p->texture_reflection)
8225                                 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);
8226                         if (!p->texture_reflection)
8227                                 goto error;
8228                 }
8229         }
8230
8231         // render views
8232         r_refdef.view = originalview;
8233         r_refdef.view.showdebug = false;
8234         r_refdef.view.width = r_waterstate.waterwidth;
8235         r_refdef.view.height = r_waterstate.waterheight;
8236         r_refdef.view.useclipplane = true;
8237         myview = r_refdef.view;
8238         r_waterstate.renderingscene = true;
8239         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8240         {
8241                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8242                 {
8243                         r_refdef.view = myview;
8244                         if(r_water_scissormode.integer)
8245                         {
8246                                 R_SetupView(true);
8247                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8248                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8249                         }
8250
8251                         // render reflected scene and copy into texture
8252                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8253                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8254                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8255                         r_refdef.view.clipplane = p->plane;
8256
8257                         // reverse the cullface settings for this render
8258                         r_refdef.view.cullface_front = GL_FRONT;
8259                         r_refdef.view.cullface_back = GL_BACK;
8260                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8261                         {
8262                                 r_refdef.view.usecustompvs = true;
8263                                 if (p->pvsvalid)
8264                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8265                                 else
8266                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8267                         }
8268
8269                         R_ResetViewRendering3D();
8270                         R_ClearScreen(r_refdef.fogenabled);
8271                         if(r_water_scissormode.integer & 2)
8272                                 R_View_UpdateWithScissor(myscissor);
8273                         else
8274                                 R_View_Update();
8275                         if(r_water_scissormode.integer & 1)
8276                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8277                         R_RenderScene();
8278
8279                         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);
8280                 }
8281
8282                 // render the normal view scene and copy into texture
8283                 // (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)
8284                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8285                 {
8286                         r_refdef.view = myview;
8287                         if(r_water_scissormode.integer)
8288                         {
8289                                 R_SetupView(true);
8290                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8291                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8292                         }
8293
8294                         r_waterstate.renderingrefraction = true;
8295
8296                         r_refdef.view.clipplane = p->plane;
8297                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8298                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8299
8300                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8301                         {
8302                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8303                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8304                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8305                                 R_RenderView_UpdateViewVectors();
8306                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8307                                 {
8308                                         r_refdef.view.usecustompvs = true;
8309                                         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);
8310                                 }
8311                         }
8312
8313                         PlaneClassify(&r_refdef.view.clipplane);
8314
8315                         R_ResetViewRendering3D();
8316                         R_ClearScreen(r_refdef.fogenabled);
8317                         if(r_water_scissormode.integer & 2)
8318                                 R_View_UpdateWithScissor(myscissor);
8319                         else
8320                                 R_View_Update();
8321                         if(r_water_scissormode.integer & 1)
8322                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8323                         R_RenderScene();
8324
8325                         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);
8326                         r_waterstate.renderingrefraction = false;
8327                 }
8328                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8329                 {
8330                         r_refdef.view = myview;
8331
8332                         r_refdef.view.clipplane = p->plane;
8333                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8334                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8335
8336                         r_refdef.view.width = r_waterstate.camerawidth;
8337                         r_refdef.view.height = r_waterstate.cameraheight;
8338                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8339                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8340
8341                         if(p->camera_entity)
8342                         {
8343                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8344                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8345                         }
8346
8347                         // note: all of the view is used for displaying... so
8348                         // there is no use in scissoring
8349
8350                         // reverse the cullface settings for this render
8351                         r_refdef.view.cullface_front = GL_FRONT;
8352                         r_refdef.view.cullface_back = GL_BACK;
8353                         // also reverse the view matrix
8354                         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
8355                         R_RenderView_UpdateViewVectors();
8356                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8357                         {
8358                                 r_refdef.view.usecustompvs = true;
8359                                 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);
8360                         }
8361                         
8362                         // camera needs no clipplane
8363                         r_refdef.view.useclipplane = false;
8364
8365                         PlaneClassify(&r_refdef.view.clipplane);
8366
8367                         R_ResetViewRendering3D();
8368                         R_ClearScreen(r_refdef.fogenabled);
8369                         R_View_Update();
8370                         R_RenderScene();
8371
8372                         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);
8373                         r_waterstate.renderingrefraction = false;
8374                 }
8375
8376         }
8377         r_waterstate.renderingscene = false;
8378         r_refdef.view = originalview;
8379         R_ResetViewRendering3D();
8380         R_ClearScreen(r_refdef.fogenabled);
8381         R_View_Update();
8382         return;
8383 error:
8384         r_refdef.view = originalview;
8385         r_waterstate.renderingscene = false;
8386         Cvar_SetValueQuick(&r_water, 0);
8387         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8388         return;
8389 }
8390
8391 void R_Bloom_StartFrame(void)
8392 {
8393         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8394
8395         switch(vid.renderpath)
8396         {
8397         case RENDERPATH_GL20:
8398         case RENDERPATH_D3D9:
8399         case RENDERPATH_D3D10:
8400         case RENDERPATH_D3D11:
8401         case RENDERPATH_SOFT:
8402         case RENDERPATH_GLES2:
8403                 break;
8404         case RENDERPATH_GL13:
8405         case RENDERPATH_GL11:
8406                 return;
8407         }
8408
8409         // set bloomwidth and bloomheight to the bloom resolution that will be
8410         // used (often less than the screen resolution for faster rendering)
8411         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8412         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8413         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8414         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8415         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8416
8417         // calculate desired texture sizes
8418         if (vid.support.arb_texture_non_power_of_two)
8419         {
8420                 screentexturewidth = r_refdef.view.width;
8421                 screentextureheight = r_refdef.view.height;
8422                 bloomtexturewidth = r_bloomstate.bloomwidth;
8423                 bloomtextureheight = r_bloomstate.bloomheight;
8424         }
8425         else
8426         {
8427                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8428                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8429                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8430                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8431         }
8432
8433         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))
8434         {
8435                 Cvar_SetValueQuick(&r_hdr, 0);
8436                 Cvar_SetValueQuick(&r_bloom, 0);
8437                 Cvar_SetValueQuick(&r_motionblur, 0);
8438                 Cvar_SetValueQuick(&r_damageblur, 0);
8439         }
8440
8441         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)))
8442                 screentexturewidth = screentextureheight = 0;
8443         if (!r_hdr.integer && !r_bloom.integer)
8444                 bloomtexturewidth = bloomtextureheight = 0;
8445
8446         // allocate textures as needed
8447         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8448         {
8449                 if (r_bloomstate.texture_screen)
8450                         R_FreeTexture(r_bloomstate.texture_screen);
8451                 r_bloomstate.texture_screen = NULL;
8452                 r_bloomstate.screentexturewidth = screentexturewidth;
8453                 r_bloomstate.screentextureheight = screentextureheight;
8454                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8455                         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);
8456         }
8457         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8458         {
8459                 if (r_bloomstate.texture_bloom)
8460                         R_FreeTexture(r_bloomstate.texture_bloom);
8461                 r_bloomstate.texture_bloom = NULL;
8462                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8463                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8464                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8465                         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);
8466         }
8467
8468         // when doing a reduced render (HDR) we want to use a smaller area
8469         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8470         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8471         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8472         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8473         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8474
8475         // set up a texcoord array for the full resolution screen image
8476         // (we have to keep this around to copy back during final render)
8477         r_bloomstate.screentexcoord2f[0] = 0;
8478         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8479         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8480         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8481         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8482         r_bloomstate.screentexcoord2f[5] = 0;
8483         r_bloomstate.screentexcoord2f[6] = 0;
8484         r_bloomstate.screentexcoord2f[7] = 0;
8485
8486         // set up a texcoord array for the reduced resolution bloom image
8487         // (which will be additive blended over the screen image)
8488         r_bloomstate.bloomtexcoord2f[0] = 0;
8489         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8490         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8491         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8492         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8493         r_bloomstate.bloomtexcoord2f[5] = 0;
8494         r_bloomstate.bloomtexcoord2f[6] = 0;
8495         r_bloomstate.bloomtexcoord2f[7] = 0;
8496
8497         switch(vid.renderpath)
8498         {
8499         case RENDERPATH_GL11:
8500         case RENDERPATH_GL13:
8501         case RENDERPATH_GL20:
8502         case RENDERPATH_SOFT:
8503         case RENDERPATH_GLES2:
8504                 break;
8505         case RENDERPATH_D3D9:
8506         case RENDERPATH_D3D10:
8507         case RENDERPATH_D3D11:
8508                 {
8509                         int i;
8510                         for (i = 0;i < 4;i++)
8511                         {
8512                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8513                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8514                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8515                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8516                         }
8517                 }
8518                 break;
8519         }
8520
8521         if (r_hdr.integer || r_bloom.integer)
8522         {
8523                 r_bloomstate.enabled = true;
8524                 r_bloomstate.hdr = r_hdr.integer != 0;
8525         }
8526
8527         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);
8528 }
8529
8530 void R_Bloom_CopyBloomTexture(float colorscale)
8531 {
8532         r_refdef.stats.bloom++;
8533
8534         // scale down screen texture to the bloom texture size
8535         CHECKGLERROR
8536         R_SetViewport(&r_bloomstate.viewport);
8537         GL_BlendFunc(GL_ONE, GL_ZERO);
8538         GL_Color(colorscale, colorscale, colorscale, 1);
8539         // 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...
8540         switch(vid.renderpath)
8541         {
8542         case RENDERPATH_GL11:
8543         case RENDERPATH_GL13:
8544         case RENDERPATH_GL20:
8545         case RENDERPATH_SOFT:
8546         case RENDERPATH_GLES2:
8547                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8548                 break;
8549         case RENDERPATH_D3D9:
8550         case RENDERPATH_D3D10:
8551         case RENDERPATH_D3D11:
8552                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8553                 break;
8554         }
8555         // TODO: do boxfilter scale-down in shader?
8556         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8557         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8558         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8559
8560         // we now have a bloom image in the framebuffer
8561         // copy it into the bloom image texture for later processing
8562         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);
8563         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8564 }
8565
8566 void R_Bloom_CopyHDRTexture(void)
8567 {
8568         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);
8569         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8570 }
8571
8572 void R_Bloom_MakeTexture(void)
8573 {
8574         int x, range, dir;
8575         float xoffset, yoffset, r, brighten;
8576
8577         r_refdef.stats.bloom++;
8578
8579         R_ResetViewRendering2D();
8580
8581         // we have a bloom image in the framebuffer
8582         CHECKGLERROR
8583         R_SetViewport(&r_bloomstate.viewport);
8584
8585         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8586         {
8587                 x *= 2;
8588                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8589                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8590                 GL_Color(r,r,r,1);
8591                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8592                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8593                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8594                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8595
8596                 // copy the vertically blurred bloom view to a texture
8597                 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);
8598                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8599         }
8600
8601         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8602         brighten = r_bloom_brighten.value;
8603         if (r_hdr.integer)
8604                 brighten *= r_hdr_range.value;
8605         brighten = sqrt(brighten);
8606         if(range >= 1)
8607                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8608         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8609
8610         for (dir = 0;dir < 2;dir++)
8611         {
8612                 // blend on at multiple vertical offsets to achieve a vertical blur
8613                 // TODO: do offset blends using GLSL
8614                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8615                 GL_BlendFunc(GL_ONE, GL_ZERO);
8616                 for (x = -range;x <= range;x++)
8617                 {
8618                         if (!dir){xoffset = 0;yoffset = x;}
8619                         else {xoffset = x;yoffset = 0;}
8620                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8621                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8622                         // compute a texcoord array with the specified x and y offset
8623                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8624                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8625                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8626                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8627                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8628                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8629                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8630                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8631                         // this r value looks like a 'dot' particle, fading sharply to
8632                         // black at the edges
8633                         // (probably not realistic but looks good enough)
8634                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8635                         //r = brighten/(range*2+1);
8636                         r = brighten / (range * 2 + 1);
8637                         if(range >= 1)
8638                                 r *= (1 - x*x/(float)(range*range));
8639                         GL_Color(r, r, r, 1);
8640                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8641                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8642                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8643                         GL_BlendFunc(GL_ONE, GL_ONE);
8644                 }
8645
8646                 // copy the vertically blurred bloom view to a texture
8647                 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);
8648                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8649         }
8650 }
8651
8652 void R_HDR_RenderBloomTexture(void)
8653 {
8654         int oldwidth, oldheight;
8655         float oldcolorscale;
8656         qboolean oldwaterstate;
8657
8658         oldwaterstate = r_waterstate.enabled;
8659         oldcolorscale = r_refdef.view.colorscale;
8660         oldwidth = r_refdef.view.width;
8661         oldheight = r_refdef.view.height;
8662         r_refdef.view.width = r_bloomstate.bloomwidth;
8663         r_refdef.view.height = r_bloomstate.bloomheight;
8664
8665         if(r_hdr.integer < 2)
8666                 r_waterstate.enabled = false;
8667
8668         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8669         // TODO: add exposure compensation features
8670         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8671
8672         r_refdef.view.showdebug = false;
8673         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8674
8675         R_ResetViewRendering3D();
8676
8677         R_ClearScreen(r_refdef.fogenabled);
8678         if (r_timereport_active)
8679                 R_TimeReport("HDRclear");
8680
8681         R_View_Update();
8682         if (r_timereport_active)
8683                 R_TimeReport("visibility");
8684
8685         // only do secondary renders with HDR if r_hdr is 2 or higher
8686         r_waterstate.numwaterplanes = 0;
8687         if (r_waterstate.enabled)
8688                 R_RenderWaterPlanes();
8689
8690         r_refdef.view.showdebug = true;
8691         R_RenderScene();
8692         r_waterstate.numwaterplanes = 0;
8693
8694         R_ResetViewRendering2D();
8695
8696         R_Bloom_CopyHDRTexture();
8697         R_Bloom_MakeTexture();
8698
8699         // restore the view settings
8700         r_waterstate.enabled = oldwaterstate;
8701         r_refdef.view.width = oldwidth;
8702         r_refdef.view.height = oldheight;
8703         r_refdef.view.colorscale = oldcolorscale;
8704
8705         R_ResetViewRendering3D();
8706
8707         R_ClearScreen(r_refdef.fogenabled);
8708         if (r_timereport_active)
8709                 R_TimeReport("viewclear");
8710 }
8711
8712 static void R_BlendView(void)
8713 {
8714         unsigned int permutation;
8715         float uservecs[4][4];
8716
8717         switch (vid.renderpath)
8718         {
8719         case RENDERPATH_GL20:
8720         case RENDERPATH_D3D9:
8721         case RENDERPATH_D3D10:
8722         case RENDERPATH_D3D11:
8723         case RENDERPATH_SOFT:
8724         case RENDERPATH_GLES2:
8725                 permutation =
8726                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8727                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8728                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8729                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8730                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8731
8732                 if (r_bloomstate.texture_screen)
8733                 {
8734                         // make sure the buffer is available
8735                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8736
8737                         R_ResetViewRendering2D();
8738
8739                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8740                         {
8741                                 // declare variables
8742                                 float speed;
8743                                 static float avgspeed;
8744
8745                                 speed = VectorLength(cl.movement_velocity);
8746
8747                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8748                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8749
8750                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8751                                 speed = bound(0, speed, 1);
8752                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8753
8754                                 // calculate values into a standard alpha
8755                                 cl.motionbluralpha = 1 - exp(-
8756                                                 (
8757                                                  (r_motionblur.value * speed / 80)
8758                                                  +
8759                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8760                                                 )
8761                                                 /
8762                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8763                                            );
8764
8765                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8766                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8767                                 // apply the blur
8768                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8769                                 {
8770                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8771                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8772                                         switch(vid.renderpath)
8773                                         {
8774                                         case RENDERPATH_GL11:
8775                                         case RENDERPATH_GL13:
8776                                         case RENDERPATH_GL20:
8777                                         case RENDERPATH_SOFT:
8778                                         case RENDERPATH_GLES2:
8779                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8780                                                 break;
8781                                         case RENDERPATH_D3D9:
8782                                         case RENDERPATH_D3D10:
8783                                         case RENDERPATH_D3D11:
8784                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8785                                                 break;
8786                                         }
8787                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8788                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8789                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8790                                 }
8791                         }
8792
8793                         // copy view into the screen texture
8794                         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);
8795                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8796                 }
8797                 else if (!r_bloomstate.texture_bloom)
8798                 {
8799                         // we may still have to do view tint...
8800                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8801                         {
8802                                 // apply a color tint to the whole view
8803                                 R_ResetViewRendering2D();
8804                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8805                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8806                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8807                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8808                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8809                         }
8810                         break; // no screen processing, no bloom, skip it
8811                 }
8812
8813                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8814                 {
8815                         // render simple bloom effect
8816                         // copy the screen and shrink it and darken it for the bloom process
8817                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8818                         // make the bloom texture
8819                         R_Bloom_MakeTexture();
8820                 }
8821
8822 #if _MSC_VER >= 1400
8823 #define sscanf sscanf_s
8824 #endif
8825                 memset(uservecs, 0, sizeof(uservecs));
8826                 if (r_glsl_postprocess_uservec1_enable.integer)
8827                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8828                 if (r_glsl_postprocess_uservec2_enable.integer)
8829                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8830                 if (r_glsl_postprocess_uservec3_enable.integer)
8831                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8832                 if (r_glsl_postprocess_uservec4_enable.integer)
8833                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8834
8835                 R_ResetViewRendering2D();
8836                 GL_Color(1, 1, 1, 1);
8837                 GL_BlendFunc(GL_ONE, GL_ZERO);
8838
8839                 switch(vid.renderpath)
8840                 {
8841                 case RENDERPATH_GL20:
8842                 case RENDERPATH_GLES2:
8843                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8844                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8845                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
8846                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
8847                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
8848                         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]);
8849                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8850                         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]);
8851                         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]);
8852                         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]);
8853                         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]);
8854                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8855                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8856                         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);
8857                         break;
8858                 case RENDERPATH_D3D9:
8859 #ifdef SUPPORTD3D
8860                         // 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...
8861                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8862                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
8863                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8864                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8865                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8866                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8867                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8868                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8869                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8870                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8871                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8872                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
8873                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
8874                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8875 #endif
8876                         break;
8877                 case RENDERPATH_D3D10:
8878                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8879                         break;
8880                 case RENDERPATH_D3D11:
8881                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8882                         break;
8883                 case RENDERPATH_SOFT:
8884                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8885                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
8886                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8887                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8888                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8889                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8890                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8891                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8892                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8893                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8894                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8895                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
8896                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8897                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8898                         break;
8899                 default:
8900                         break;
8901                 }
8902                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8903                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8904                 break;
8905         case RENDERPATH_GL13:
8906         case RENDERPATH_GL11:
8907                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8908                 {
8909                         // apply a color tint to the whole view
8910                         R_ResetViewRendering2D();
8911                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8912                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8913                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8914                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8915                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8916                 }
8917                 break;
8918         }
8919 }
8920
8921 matrix4x4_t r_waterscrollmatrix;
8922
8923 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8924 {
8925         if (r_refdef.fog_density)
8926         {
8927                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8928                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8929                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8930
8931                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8932                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8933                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8934                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8935
8936                 {
8937                         vec3_t fogvec;
8938                         VectorCopy(r_refdef.fogcolor, fogvec);
8939                         //   color.rgb *= ContrastBoost * SceneBrightness;
8940                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8941                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8942                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8943                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8944                 }
8945         }
8946 }
8947
8948 void R_UpdateVariables(void)
8949 {
8950         R_Textures_Frame();
8951
8952         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8953
8954         r_refdef.farclip = r_farclip_base.value;
8955         if (r_refdef.scene.worldmodel)
8956                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8957         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8958
8959         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8960                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8961         r_refdef.polygonfactor = 0;
8962         r_refdef.polygonoffset = 0;
8963         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8964         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8965
8966         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8967         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8968         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
8969         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8970         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8971         if (FAKELIGHT_ENABLED)
8972         {
8973                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
8974         }
8975         if (r_showsurfaces.integer)
8976         {
8977                 r_refdef.scene.rtworld = false;
8978                 r_refdef.scene.rtworldshadows = false;
8979                 r_refdef.scene.rtdlight = false;
8980                 r_refdef.scene.rtdlightshadows = false;
8981                 r_refdef.lightmapintensity = 0;
8982         }
8983
8984         if (gamemode == GAME_NEHAHRA)
8985         {
8986                 if (gl_fogenable.integer)
8987                 {
8988                         r_refdef.oldgl_fogenable = true;
8989                         r_refdef.fog_density = gl_fogdensity.value;
8990                         r_refdef.fog_red = gl_fogred.value;
8991                         r_refdef.fog_green = gl_foggreen.value;
8992                         r_refdef.fog_blue = gl_fogblue.value;
8993                         r_refdef.fog_alpha = 1;
8994                         r_refdef.fog_start = 0;
8995                         r_refdef.fog_end = gl_skyclip.value;
8996                         r_refdef.fog_height = 1<<30;
8997                         r_refdef.fog_fadedepth = 128;
8998                 }
8999                 else if (r_refdef.oldgl_fogenable)
9000                 {
9001                         r_refdef.oldgl_fogenable = false;
9002                         r_refdef.fog_density = 0;
9003                         r_refdef.fog_red = 0;
9004                         r_refdef.fog_green = 0;
9005                         r_refdef.fog_blue = 0;
9006                         r_refdef.fog_alpha = 0;
9007                         r_refdef.fog_start = 0;
9008                         r_refdef.fog_end = 0;
9009                         r_refdef.fog_height = 1<<30;
9010                         r_refdef.fog_fadedepth = 128;
9011                 }
9012         }
9013
9014         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9015         r_refdef.fog_start = max(0, r_refdef.fog_start);
9016         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9017
9018         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9019
9020         if (r_refdef.fog_density && r_drawfog.integer)
9021         {
9022                 r_refdef.fogenabled = true;
9023                 // this is the point where the fog reaches 0.9986 alpha, which we
9024                 // consider a good enough cutoff point for the texture
9025                 // (0.9986 * 256 == 255.6)
9026                 if (r_fog_exp2.integer)
9027                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9028                 else
9029                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9030                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9031                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9032                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9033                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9034                         R_BuildFogHeightTexture();
9035                 // fog color was already set
9036                 // update the fog texture
9037                 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)
9038                         R_BuildFogTexture();
9039                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9040                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9041         }
9042         else
9043                 r_refdef.fogenabled = false;
9044
9045         switch(vid.renderpath)
9046         {
9047         case RENDERPATH_GL20:
9048         case RENDERPATH_D3D9:
9049         case RENDERPATH_D3D10:
9050         case RENDERPATH_D3D11:
9051         case RENDERPATH_SOFT:
9052         case RENDERPATH_GLES2:
9053                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9054                 {
9055                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9056                         {
9057                                 // build GLSL gamma texture
9058 #define RAMPWIDTH 256
9059                                 unsigned short ramp[RAMPWIDTH * 3];
9060                                 unsigned char rampbgr[RAMPWIDTH][4];
9061                                 int i;
9062
9063                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9064
9065                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9066                                 for(i = 0; i < RAMPWIDTH; ++i)
9067                                 {
9068                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9069                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9070                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9071                                         rampbgr[i][3] = 0;
9072                                 }
9073                                 if (r_texture_gammaramps)
9074                                 {
9075                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
9076                                 }
9077                                 else
9078                                 {
9079                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9080                                 }
9081                         }
9082                 }
9083                 else
9084                 {
9085                         // remove GLSL gamma texture
9086                 }
9087                 break;
9088         case RENDERPATH_GL13:
9089         case RENDERPATH_GL11:
9090                 break;
9091         }
9092 }
9093
9094 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9095 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9096 /*
9097 ================
9098 R_SelectScene
9099 ================
9100 */
9101 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9102         if( scenetype != r_currentscenetype ) {
9103                 // store the old scenetype
9104                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9105                 r_currentscenetype = scenetype;
9106                 // move in the new scene
9107                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9108         }
9109 }
9110
9111 /*
9112 ================
9113 R_GetScenePointer
9114 ================
9115 */
9116 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9117 {
9118         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9119         if( scenetype == r_currentscenetype ) {
9120                 return &r_refdef.scene;
9121         } else {
9122                 return &r_scenes_store[ scenetype ];
9123         }
9124 }
9125
9126 /*
9127 ================
9128 R_RenderView
9129 ================
9130 */
9131 int dpsoftrast_test;
9132 void R_RenderView(void)
9133 {
9134         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9135
9136         dpsoftrast_test = r_test.integer;
9137
9138         if (r_timereport_active)
9139                 R_TimeReport("start");
9140         r_textureframe++; // used only by R_GetCurrentTexture
9141         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9142
9143         if(R_CompileShader_CheckStaticParms())
9144                 R_GLSL_Restart_f();
9145
9146         if (!r_drawentities.integer)
9147                 r_refdef.scene.numentities = 0;
9148
9149         R_AnimCache_ClearCache();
9150         R_FrameData_NewFrame();
9151
9152         /* adjust for stereo display */
9153         if(R_Stereo_Active())
9154         {
9155                 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);
9156                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9157         }
9158
9159         if (r_refdef.view.isoverlay)
9160         {
9161                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9162                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9163                 R_TimeReport("depthclear");
9164
9165                 r_refdef.view.showdebug = false;
9166
9167                 r_waterstate.enabled = false;
9168                 r_waterstate.numwaterplanes = 0;
9169
9170                 R_RenderScene();
9171
9172                 r_refdef.view.matrix = originalmatrix;
9173
9174                 CHECKGLERROR
9175                 return;
9176         }
9177
9178         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9179         {
9180                 r_refdef.view.matrix = originalmatrix;
9181                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9182         }
9183
9184         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
9185
9186         R_RenderView_UpdateViewVectors();
9187
9188         R_Shadow_UpdateWorldLightSelection();
9189
9190         R_Bloom_StartFrame();
9191         R_Water_StartFrame();
9192
9193         CHECKGLERROR
9194         if (r_timereport_active)
9195                 R_TimeReport("viewsetup");
9196
9197         R_ResetViewRendering3D();
9198
9199         if (r_refdef.view.clear || r_refdef.fogenabled)
9200         {
9201                 R_ClearScreen(r_refdef.fogenabled);
9202                 if (r_timereport_active)
9203                         R_TimeReport("viewclear");
9204         }
9205         r_refdef.view.clear = true;
9206
9207         // this produces a bloom texture to be used in R_BlendView() later
9208         if (r_hdr.integer && r_bloomstate.bloomwidth)
9209         {
9210                 R_HDR_RenderBloomTexture();
9211                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9212                 r_textureframe++; // used only by R_GetCurrentTexture
9213         }
9214
9215         r_refdef.view.showdebug = true;
9216
9217         R_View_Update();
9218         if (r_timereport_active)
9219                 R_TimeReport("visibility");
9220
9221         r_waterstate.numwaterplanes = 0;
9222         if (r_waterstate.enabled)
9223                 R_RenderWaterPlanes();
9224
9225         R_RenderScene();
9226         r_waterstate.numwaterplanes = 0;
9227
9228         R_BlendView();
9229         if (r_timereport_active)
9230                 R_TimeReport("blendview");
9231
9232         GL_Scissor(0, 0, vid.width, vid.height);
9233         GL_ScissorTest(false);
9234
9235         r_refdef.view.matrix = originalmatrix;
9236
9237         CHECKGLERROR
9238 }
9239
9240 void R_RenderWaterPlanes(void)
9241 {
9242         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9243         {
9244                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9245                 if (r_timereport_active)
9246                         R_TimeReport("waterworld");
9247         }
9248
9249         // don't let sound skip if going slow
9250         if (r_refdef.scene.extraupdate)
9251                 S_ExtraUpdate ();
9252
9253         R_DrawModelsAddWaterPlanes();
9254         if (r_timereport_active)
9255                 R_TimeReport("watermodels");
9256
9257         if (r_waterstate.numwaterplanes)
9258         {
9259                 R_Water_ProcessPlanes();
9260                 if (r_timereport_active)
9261                         R_TimeReport("waterscenes");
9262         }
9263 }
9264
9265 extern void R_DrawLightningBeams (void);
9266 extern void VM_CL_AddPolygonsToMeshQueue (void);
9267 extern void R_DrawPortals (void);
9268 extern cvar_t cl_locs_show;
9269 static void R_DrawLocs(void);
9270 static void R_DrawEntityBBoxes(void);
9271 static void R_DrawModelDecals(void);
9272 extern void R_DrawModelShadows(void);
9273 extern void R_DrawModelShadowMaps(void);
9274 extern cvar_t cl_decals_newsystem;
9275 extern qboolean r_shadow_usingdeferredprepass;
9276 void R_RenderScene(void)
9277 {
9278         qboolean shadowmapping = false;
9279
9280         if (r_timereport_active)
9281                 R_TimeReport("beginscene");
9282
9283         r_refdef.stats.renders++;
9284
9285         R_UpdateFogColor();
9286
9287         // don't let sound skip if going slow
9288         if (r_refdef.scene.extraupdate)
9289                 S_ExtraUpdate ();
9290
9291         R_MeshQueue_BeginScene();
9292
9293         R_SkyStartFrame();
9294
9295         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);
9296
9297         if (r_timereport_active)
9298                 R_TimeReport("skystartframe");
9299
9300         if (cl.csqc_vidvars.drawworld)
9301         {
9302                 // don't let sound skip if going slow
9303                 if (r_refdef.scene.extraupdate)
9304                         S_ExtraUpdate ();
9305
9306                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9307                 {
9308                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9309                         if (r_timereport_active)
9310                                 R_TimeReport("worldsky");
9311                 }
9312
9313                 if (R_DrawBrushModelsSky() && r_timereport_active)
9314                         R_TimeReport("bmodelsky");
9315
9316                 if (skyrendermasked && skyrenderlater)
9317                 {
9318                         // we have to force off the water clipping plane while rendering sky
9319                         R_SetupView(false);
9320                         R_Sky();
9321                         R_SetupView(true);
9322                         if (r_timereport_active)
9323                                 R_TimeReport("sky");
9324                 }
9325         }
9326
9327         R_AnimCache_CacheVisibleEntities();
9328         if (r_timereport_active)
9329                 R_TimeReport("animation");
9330
9331         R_Shadow_PrepareLights();
9332         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9333                 R_Shadow_PrepareModelShadows();
9334         if (r_timereport_active)
9335                 R_TimeReport("preparelights");
9336
9337         if (R_Shadow_ShadowMappingEnabled())
9338                 shadowmapping = true;
9339
9340         if (r_shadow_usingdeferredprepass)
9341                 R_Shadow_DrawPrepass();
9342
9343         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9344         {
9345                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9346                 if (r_timereport_active)
9347                         R_TimeReport("worlddepth");
9348         }
9349         if (r_depthfirst.integer >= 2)
9350         {
9351                 R_DrawModelsDepth();
9352                 if (r_timereport_active)
9353                         R_TimeReport("modeldepth");
9354         }
9355
9356         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9357         {
9358                 R_DrawModelShadowMaps();
9359                 R_ResetViewRendering3D();
9360                 // don't let sound skip if going slow
9361                 if (r_refdef.scene.extraupdate)
9362                         S_ExtraUpdate ();
9363         }
9364
9365         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9366         {
9367                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9368                 if (r_timereport_active)
9369                         R_TimeReport("world");
9370         }
9371
9372         // don't let sound skip if going slow
9373         if (r_refdef.scene.extraupdate)
9374                 S_ExtraUpdate ();
9375
9376         R_DrawModels();
9377         if (r_timereport_active)
9378                 R_TimeReport("models");
9379
9380         // don't let sound skip if going slow
9381         if (r_refdef.scene.extraupdate)
9382                 S_ExtraUpdate ();
9383
9384         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9385         {
9386                 R_DrawModelShadows();
9387                 R_ResetViewRendering3D();
9388                 // don't let sound skip if going slow
9389                 if (r_refdef.scene.extraupdate)
9390                         S_ExtraUpdate ();
9391         }
9392
9393         if (!r_shadow_usingdeferredprepass)
9394         {
9395                 R_Shadow_DrawLights();
9396                 if (r_timereport_active)
9397                         R_TimeReport("rtlights");
9398         }
9399
9400         // don't let sound skip if going slow
9401         if (r_refdef.scene.extraupdate)
9402                 S_ExtraUpdate ();
9403
9404         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9405         {
9406                 R_DrawModelShadows();
9407                 R_ResetViewRendering3D();
9408                 // don't let sound skip if going slow
9409                 if (r_refdef.scene.extraupdate)
9410                         S_ExtraUpdate ();
9411         }
9412
9413         if (cl.csqc_vidvars.drawworld)
9414         {
9415                 if (cl_decals_newsystem.integer)
9416                 {
9417                         R_DrawModelDecals();
9418                         if (r_timereport_active)
9419                                 R_TimeReport("modeldecals");
9420                 }
9421                 else
9422                 {
9423                         R_DrawDecals();
9424                         if (r_timereport_active)
9425                                 R_TimeReport("decals");
9426                 }
9427
9428                 R_DrawParticles();
9429                 if (r_timereport_active)
9430                         R_TimeReport("particles");
9431
9432                 R_DrawExplosions();
9433                 if (r_timereport_active)
9434                         R_TimeReport("explosions");
9435
9436                 R_DrawLightningBeams();
9437                 if (r_timereport_active)
9438                         R_TimeReport("lightning");
9439         }
9440
9441         VM_CL_AddPolygonsToMeshQueue();
9442
9443         if (r_refdef.view.showdebug)
9444         {
9445                 if (cl_locs_show.integer)
9446                 {
9447                         R_DrawLocs();
9448                         if (r_timereport_active)
9449                                 R_TimeReport("showlocs");
9450                 }
9451
9452                 if (r_drawportals.integer)
9453                 {
9454                         R_DrawPortals();
9455                         if (r_timereport_active)
9456                                 R_TimeReport("portals");
9457                 }
9458
9459                 if (r_showbboxes.value > 0)
9460                 {
9461                         R_DrawEntityBBoxes();
9462                         if (r_timereport_active)
9463                                 R_TimeReport("bboxes");
9464                 }
9465         }
9466
9467         R_MeshQueue_RenderTransparent();
9468         if (r_timereport_active)
9469                 R_TimeReport("drawtrans");
9470
9471         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))
9472         {
9473                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9474                 if (r_timereport_active)
9475                         R_TimeReport("worlddebug");
9476                 R_DrawModelsDebug();
9477                 if (r_timereport_active)
9478                         R_TimeReport("modeldebug");
9479         }
9480
9481         if (cl.csqc_vidvars.drawworld)
9482         {
9483                 R_Shadow_DrawCoronas();
9484                 if (r_timereport_active)
9485                         R_TimeReport("coronas");
9486         }
9487
9488 #if 0
9489         {
9490                 GL_DepthTest(false);
9491                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9492                 GL_Color(1, 1, 1, 1);
9493                 qglBegin(GL_POLYGON);
9494                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9495                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9496                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9497                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9498                 qglEnd();
9499                 qglBegin(GL_POLYGON);
9500                 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]);
9501                 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]);
9502                 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]);
9503                 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]);
9504                 qglEnd();
9505                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9506         }
9507 #endif
9508
9509         // don't let sound skip if going slow
9510         if (r_refdef.scene.extraupdate)
9511                 S_ExtraUpdate ();
9512
9513         R_ResetViewRendering2D();
9514 }
9515
9516 static const unsigned short bboxelements[36] =
9517 {
9518         5, 1, 3, 5, 3, 7,
9519         6, 2, 0, 6, 0, 4,
9520         7, 3, 2, 7, 2, 6,
9521         4, 0, 1, 4, 1, 5,
9522         4, 5, 7, 4, 7, 6,
9523         1, 0, 2, 1, 2, 3,
9524 };
9525
9526 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9527 {
9528         int i;
9529         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9530
9531         RSurf_ActiveWorldEntity();
9532
9533         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9534         GL_DepthMask(false);
9535         GL_DepthRange(0, 1);
9536         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9537 //      R_Mesh_ResetTextureState();
9538
9539         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9540         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9541         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9542         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9543         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9544         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9545         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9546         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9547         R_FillColors(color4f, 8, cr, cg, cb, ca);
9548         if (r_refdef.fogenabled)
9549         {
9550                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9551                 {
9552                         f1 = RSurf_FogVertex(v);
9553                         f2 = 1 - f1;
9554                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9555                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9556                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9557                 }
9558         }
9559         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9560         R_Mesh_ResetTextureState();
9561         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9562         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9563 }
9564
9565 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9566 {
9567         int i;
9568         float color[4];
9569         prvm_edict_t *edict;
9570         prvm_prog_t *prog_save = prog;
9571
9572         // this function draws bounding boxes of server entities
9573         if (!sv.active)
9574                 return;
9575
9576         GL_CullFace(GL_NONE);
9577         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9578
9579         prog = 0;
9580         SV_VM_Begin();
9581         for (i = 0;i < numsurfaces;i++)
9582         {
9583                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9584                 switch ((int)edict->fields.server->solid)
9585                 {
9586                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9587                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9588                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9589                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9590                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9591                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9592                 }
9593                 color[3] *= r_showbboxes.value;
9594                 color[3] = bound(0, color[3], 1);
9595                 GL_DepthTest(!r_showdisabledepthtest.integer);
9596                 GL_CullFace(r_refdef.view.cullface_front);
9597                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9598         }
9599         SV_VM_End();
9600         prog = prog_save;
9601 }
9602
9603 static void R_DrawEntityBBoxes(void)
9604 {
9605         int i;
9606         prvm_edict_t *edict;
9607         vec3_t center;
9608         prvm_prog_t *prog_save = prog;
9609
9610         // this function draws bounding boxes of server entities
9611         if (!sv.active)
9612                 return;
9613
9614         prog = 0;
9615         SV_VM_Begin();
9616         for (i = 0;i < prog->num_edicts;i++)
9617         {
9618                 edict = PRVM_EDICT_NUM(i);
9619                 if (edict->priv.server->free)
9620                         continue;
9621                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9622                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9623                         continue;
9624                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9625                         continue;
9626                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9627                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9628         }
9629         SV_VM_End();
9630         prog = prog_save;
9631 }
9632
9633 static const int nomodelelement3i[24] =
9634 {
9635         5, 2, 0,
9636         5, 1, 2,
9637         5, 0, 3,
9638         5, 3, 1,
9639         0, 2, 4,
9640         2, 1, 4,
9641         3, 0, 4,
9642         1, 3, 4
9643 };
9644
9645 static const unsigned short nomodelelement3s[24] =
9646 {
9647         5, 2, 0,
9648         5, 1, 2,
9649         5, 0, 3,
9650         5, 3, 1,
9651         0, 2, 4,
9652         2, 1, 4,
9653         3, 0, 4,
9654         1, 3, 4
9655 };
9656
9657 static const float nomodelvertex3f[6*3] =
9658 {
9659         -16,   0,   0,
9660          16,   0,   0,
9661           0, -16,   0,
9662           0,  16,   0,
9663           0,   0, -16,
9664           0,   0,  16
9665 };
9666
9667 static const float nomodelcolor4f[6*4] =
9668 {
9669         0.0f, 0.0f, 0.5f, 1.0f,
9670         0.0f, 0.0f, 0.5f, 1.0f,
9671         0.0f, 0.5f, 0.0f, 1.0f,
9672         0.0f, 0.5f, 0.0f, 1.0f,
9673         0.5f, 0.0f, 0.0f, 1.0f,
9674         0.5f, 0.0f, 0.0f, 1.0f
9675 };
9676
9677 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9678 {
9679         int i;
9680         float f1, f2, *c;
9681         float color4f[6*4];
9682
9683         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);
9684
9685         // this is only called once per entity so numsurfaces is always 1, and
9686         // surfacelist is always {0}, so this code does not handle batches
9687
9688         if (rsurface.ent_flags & RENDER_ADDITIVE)
9689         {
9690                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9691                 GL_DepthMask(false);
9692         }
9693         else if (rsurface.colormod[3] < 1)
9694         {
9695                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9696                 GL_DepthMask(false);
9697         }
9698         else
9699         {
9700                 GL_BlendFunc(GL_ONE, GL_ZERO);
9701                 GL_DepthMask(true);
9702         }
9703         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9704         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9705         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9706         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9707         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9708         for (i = 0, c = color4f;i < 6;i++, c += 4)
9709         {
9710                 c[0] *= rsurface.colormod[0];
9711                 c[1] *= rsurface.colormod[1];
9712                 c[2] *= rsurface.colormod[2];
9713                 c[3] *= rsurface.colormod[3];
9714         }
9715         if (r_refdef.fogenabled)
9716         {
9717                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9718                 {
9719                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9720                         f2 = 1 - f1;
9721                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9722                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9723                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9724                 }
9725         }
9726 //      R_Mesh_ResetTextureState();
9727         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9728         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9729         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9730 }
9731
9732 void R_DrawNoModel(entity_render_t *ent)
9733 {
9734         vec3_t org;
9735         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9736         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9737                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9738         else
9739                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9740 }
9741
9742 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9743 {
9744         vec3_t right1, right2, diff, normal;
9745
9746         VectorSubtract (org2, org1, normal);
9747
9748         // calculate 'right' vector for start
9749         VectorSubtract (r_refdef.view.origin, org1, diff);
9750         CrossProduct (normal, diff, right1);
9751         VectorNormalize (right1);
9752
9753         // calculate 'right' vector for end
9754         VectorSubtract (r_refdef.view.origin, org2, diff);
9755         CrossProduct (normal, diff, right2);
9756         VectorNormalize (right2);
9757
9758         vert[ 0] = org1[0] + width * right1[0];
9759         vert[ 1] = org1[1] + width * right1[1];
9760         vert[ 2] = org1[2] + width * right1[2];
9761         vert[ 3] = org1[0] - width * right1[0];
9762         vert[ 4] = org1[1] - width * right1[1];
9763         vert[ 5] = org1[2] - width * right1[2];
9764         vert[ 6] = org2[0] - width * right2[0];
9765         vert[ 7] = org2[1] - width * right2[1];
9766         vert[ 8] = org2[2] - width * right2[2];
9767         vert[ 9] = org2[0] + width * right2[0];
9768         vert[10] = org2[1] + width * right2[1];
9769         vert[11] = org2[2] + width * right2[2];
9770 }
9771
9772 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)
9773 {
9774         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9775         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9776         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9777         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9778         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9779         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9780         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9781         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9782         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9783         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9784         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9785         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9786 }
9787
9788 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9789 {
9790         int i;
9791         float *vertex3f;
9792         float v[3];
9793         VectorSet(v, x, y, z);
9794         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9795                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9796                         break;
9797         if (i == mesh->numvertices)
9798         {
9799                 if (mesh->numvertices < mesh->maxvertices)
9800                 {
9801                         VectorCopy(v, vertex3f);
9802                         mesh->numvertices++;
9803                 }
9804                 return mesh->numvertices;
9805         }
9806         else
9807                 return i;
9808 }
9809
9810 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9811 {
9812         int i;
9813         int *e, element[3];
9814         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9815         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9816         e = mesh->element3i + mesh->numtriangles * 3;
9817         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9818         {
9819                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9820                 if (mesh->numtriangles < mesh->maxtriangles)
9821                 {
9822                         *e++ = element[0];
9823                         *e++ = element[1];
9824                         *e++ = element[2];
9825                         mesh->numtriangles++;
9826                 }
9827                 element[1] = element[2];
9828         }
9829 }
9830
9831 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9832 {
9833         int i;
9834         int *e, element[3];
9835         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9836         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9837         e = mesh->element3i + mesh->numtriangles * 3;
9838         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9839         {
9840                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9841                 if (mesh->numtriangles < mesh->maxtriangles)
9842                 {
9843                         *e++ = element[0];
9844                         *e++ = element[1];
9845                         *e++ = element[2];
9846                         mesh->numtriangles++;
9847                 }
9848                 element[1] = element[2];
9849         }
9850 }
9851
9852 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9853 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9854 {
9855         int planenum, planenum2;
9856         int w;
9857         int tempnumpoints;
9858         mplane_t *plane, *plane2;
9859         double maxdist;
9860         double temppoints[2][256*3];
9861         // figure out how large a bounding box we need to properly compute this brush
9862         maxdist = 0;
9863         for (w = 0;w < numplanes;w++)
9864                 maxdist = max(maxdist, fabs(planes[w].dist));
9865         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9866         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9867         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9868         {
9869                 w = 0;
9870                 tempnumpoints = 4;
9871                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9872                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9873                 {
9874                         if (planenum2 == planenum)
9875                                 continue;
9876                         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);
9877                         w = !w;
9878                 }
9879                 if (tempnumpoints < 3)
9880                         continue;
9881                 // generate elements forming a triangle fan for this polygon
9882                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9883         }
9884 }
9885
9886 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)
9887 {
9888         texturelayer_t *layer;
9889         layer = t->currentlayers + t->currentnumlayers++;
9890         layer->type = type;
9891         layer->depthmask = depthmask;
9892         layer->blendfunc1 = blendfunc1;
9893         layer->blendfunc2 = blendfunc2;
9894         layer->texture = texture;
9895         layer->texmatrix = *matrix;
9896         layer->color[0] = r;
9897         layer->color[1] = g;
9898         layer->color[2] = b;
9899         layer->color[3] = a;
9900 }
9901
9902 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9903 {
9904         if(parms[0] == 0 && parms[1] == 0)
9905                 return false;
9906         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9907                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9908                         return false;
9909         return true;
9910 }
9911
9912 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9913 {
9914         double index, f;
9915         index = parms[2] + r_refdef.scene.time * parms[3];
9916         index -= floor(index);
9917         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9918         {
9919         default:
9920         case Q3WAVEFUNC_NONE:
9921         case Q3WAVEFUNC_NOISE:
9922         case Q3WAVEFUNC_COUNT:
9923                 f = 0;
9924                 break;
9925         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9926         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9927         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9928         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9929         case Q3WAVEFUNC_TRIANGLE:
9930                 index *= 4;
9931                 f = index - floor(index);
9932                 if (index < 1)
9933                         f = f;
9934                 else if (index < 2)
9935                         f = 1 - f;
9936                 else if (index < 3)
9937                         f = -f;
9938                 else
9939                         f = -(1 - f);
9940                 break;
9941         }
9942         f = parms[0] + parms[1] * f;
9943         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9944                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
9945         return (float) f;
9946 }
9947
9948 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9949 {
9950         int w, h, idx;
9951         float f;
9952         float tcmat[12];
9953         matrix4x4_t matrix, temp;
9954         switch(tcmod->tcmod)
9955         {
9956                 case Q3TCMOD_COUNT:
9957                 case Q3TCMOD_NONE:
9958                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9959                                 matrix = r_waterscrollmatrix;
9960                         else
9961                                 matrix = identitymatrix;
9962                         break;
9963                 case Q3TCMOD_ENTITYTRANSLATE:
9964                         // this is used in Q3 to allow the gamecode to control texcoord
9965                         // scrolling on the entity, which is not supported in darkplaces yet.
9966                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9967                         break;
9968                 case Q3TCMOD_ROTATE:
9969                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9970                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9971                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9972                         break;
9973                 case Q3TCMOD_SCALE:
9974                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9975                         break;
9976                 case Q3TCMOD_SCROLL:
9977                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9978                         break;
9979                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9980                         w = (int) tcmod->parms[0];
9981                         h = (int) tcmod->parms[1];
9982                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9983                         f = f - floor(f);
9984                         idx = (int) floor(f * w * h);
9985                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9986                         break;
9987                 case Q3TCMOD_STRETCH:
9988                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9989                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9990                         break;
9991                 case Q3TCMOD_TRANSFORM:
9992                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
9993                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
9994                         VectorSet(tcmat +  6, 0                   , 0                , 1);
9995                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
9996                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9997                         break;
9998                 case Q3TCMOD_TURBULENT:
9999                         // this is handled in the RSurf_PrepareVertices function
10000                         matrix = identitymatrix;
10001                         break;
10002         }
10003         temp = *texmatrix;
10004         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10005 }
10006
10007 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10008 {
10009         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10010         char name[MAX_QPATH];
10011         skinframe_t *skinframe;
10012         unsigned char pixels[296*194];
10013         strlcpy(cache->name, skinname, sizeof(cache->name));
10014         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10015         if (developer_loading.integer)
10016                 Con_Printf("loading %s\n", name);
10017         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10018         if (!skinframe || !skinframe->base)
10019         {
10020                 unsigned char *f;
10021                 fs_offset_t filesize;
10022                 skinframe = NULL;
10023                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10024                 if (f)
10025                 {
10026                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10027                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10028                         Mem_Free(f);
10029                 }
10030         }
10031         cache->skinframe = skinframe;
10032 }
10033
10034 texture_t *R_GetCurrentTexture(texture_t *t)
10035 {
10036         int i;
10037         const entity_render_t *ent = rsurface.entity;
10038         dp_model_t *model = ent->model;
10039         q3shaderinfo_layer_tcmod_t *tcmod;
10040
10041         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10042                 return t->currentframe;
10043         t->update_lastrenderframe = r_textureframe;
10044         t->update_lastrenderentity = (void *)ent;
10045
10046         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10047                 t->camera_entity = ent->entitynumber;
10048         else
10049                 t->camera_entity = 0;
10050
10051         // switch to an alternate material if this is a q1bsp animated material
10052         {
10053                 texture_t *texture = t;
10054                 int s = rsurface.ent_skinnum;
10055                 if ((unsigned int)s >= (unsigned int)model->numskins)
10056                         s = 0;
10057                 if (model->skinscenes)
10058                 {
10059                         if (model->skinscenes[s].framecount > 1)
10060                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10061                         else
10062                                 s = model->skinscenes[s].firstframe;
10063                 }
10064                 if (s > 0)
10065                         t = t + s * model->num_surfaces;
10066                 if (t->animated)
10067                 {
10068                         // use an alternate animation if the entity's frame is not 0,
10069                         // and only if the texture has an alternate animation
10070                         if (rsurface.ent_alttextures && t->anim_total[1])
10071                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10072                         else
10073                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10074                 }
10075                 texture->currentframe = t;
10076         }
10077
10078         // update currentskinframe to be a qw skin or animation frame
10079         if (rsurface.ent_qwskin >= 0)
10080         {
10081                 i = rsurface.ent_qwskin;
10082                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10083                 {
10084                         r_qwskincache_size = cl.maxclients;
10085                         if (r_qwskincache)
10086                                 Mem_Free(r_qwskincache);
10087                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10088                 }
10089                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10090                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10091                 t->currentskinframe = r_qwskincache[i].skinframe;
10092                 if (t->currentskinframe == NULL)
10093                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10094         }
10095         else if (t->numskinframes >= 2)
10096                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10097         if (t->backgroundnumskinframes >= 2)
10098                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10099
10100         t->currentmaterialflags = t->basematerialflags;
10101         t->currentalpha = rsurface.colormod[3];
10102         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10103                 t->currentalpha *= r_wateralpha.value;
10104         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10105                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10106         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10107                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10108         if (!(rsurface.ent_flags & RENDER_LIGHT))
10109                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10110         else if (FAKELIGHT_ENABLED)
10111         {
10112                         // no modellight if using fakelight for the map
10113         }
10114         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10115         {
10116                 // pick a model lighting mode
10117                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10118                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10119                 else
10120                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10121         }
10122         if (rsurface.ent_flags & RENDER_ADDITIVE)
10123                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10124         else if (t->currentalpha < 1)
10125                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10126         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10127                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10128         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10129                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10130         if (t->backgroundnumskinframes)
10131                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10132         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10133         {
10134                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10135                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10136         }
10137         else
10138                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10139         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10140                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10141
10142         // there is no tcmod
10143         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10144         {
10145                 t->currenttexmatrix = r_waterscrollmatrix;
10146                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10147         }
10148         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10149         {
10150                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10151                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10152         }
10153
10154         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10155                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10156         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10157                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10158
10159         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10160         if (t->currentskinframe->qpixels)
10161                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10162         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10163         if (!t->basetexture)
10164                 t->basetexture = r_texture_notexture;
10165         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10166         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10167         t->nmaptexture = t->currentskinframe->nmap;
10168         if (!t->nmaptexture)
10169                 t->nmaptexture = r_texture_blanknormalmap;
10170         t->glosstexture = r_texture_black;
10171         t->glowtexture = t->currentskinframe->glow;
10172         t->fogtexture = t->currentskinframe->fog;
10173         t->reflectmasktexture = t->currentskinframe->reflect;
10174         if (t->backgroundnumskinframes)
10175         {
10176                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10177                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10178                 t->backgroundglosstexture = r_texture_black;
10179                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10180                 if (!t->backgroundnmaptexture)
10181                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10182         }
10183         else
10184         {
10185                 t->backgroundbasetexture = r_texture_white;
10186                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10187                 t->backgroundglosstexture = r_texture_black;
10188                 t->backgroundglowtexture = NULL;
10189         }
10190         t->specularpower = r_shadow_glossexponent.value;
10191         // TODO: store reference values for these in the texture?
10192         t->specularscale = 0;
10193         if (r_shadow_gloss.integer > 0)
10194         {
10195                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10196                 {
10197                         if (r_shadow_glossintensity.value > 0)
10198                         {
10199                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10200                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10201                                 t->specularscale = r_shadow_glossintensity.value;
10202                         }
10203                 }
10204                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10205                 {
10206                         t->glosstexture = r_texture_white;
10207                         t->backgroundglosstexture = r_texture_white;
10208                         t->specularscale = r_shadow_gloss2intensity.value;
10209                         t->specularpower = r_shadow_gloss2exponent.value;
10210                 }
10211         }
10212         t->specularscale *= t->specularscalemod;
10213         t->specularpower *= t->specularpowermod;
10214
10215         // lightmaps mode looks bad with dlights using actual texturing, so turn
10216         // off the colormap and glossmap, but leave the normalmap on as it still
10217         // accurately represents the shading involved
10218         if (gl_lightmaps.integer)
10219         {
10220                 t->basetexture = r_texture_grey128;
10221                 t->pantstexture = r_texture_black;
10222                 t->shirttexture = r_texture_black;
10223                 t->nmaptexture = r_texture_blanknormalmap;
10224                 t->glosstexture = r_texture_black;
10225                 t->glowtexture = NULL;
10226                 t->fogtexture = NULL;
10227                 t->reflectmasktexture = NULL;
10228                 t->backgroundbasetexture = NULL;
10229                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10230                 t->backgroundglosstexture = r_texture_black;
10231                 t->backgroundglowtexture = NULL;
10232                 t->specularscale = 0;
10233                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10234         }
10235
10236         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10237         VectorClear(t->dlightcolor);
10238         t->currentnumlayers = 0;
10239         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10240         {
10241                 int blendfunc1, blendfunc2;
10242                 qboolean depthmask;
10243                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10244                 {
10245                         blendfunc1 = GL_SRC_ALPHA;
10246                         blendfunc2 = GL_ONE;
10247                 }
10248                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10249                 {
10250                         blendfunc1 = GL_SRC_ALPHA;
10251                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10252                 }
10253                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10254                 {
10255                         blendfunc1 = t->customblendfunc[0];
10256                         blendfunc2 = t->customblendfunc[1];
10257                 }
10258                 else
10259                 {
10260                         blendfunc1 = GL_ONE;
10261                         blendfunc2 = GL_ZERO;
10262                 }
10263                 // don't colormod evilblend textures
10264                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10265                         VectorSet(t->lightmapcolor, 1, 1, 1);
10266                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10267                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10268                 {
10269                         // fullbright is not affected by r_refdef.lightmapintensity
10270                         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]);
10271                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10272                                 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]);
10273                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10274                                 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]);
10275                 }
10276                 else
10277                 {
10278                         vec3_t ambientcolor;
10279                         float colorscale;
10280                         // set the color tint used for lights affecting this surface
10281                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10282                         colorscale = 2;
10283                         // q3bsp has no lightmap updates, so the lightstylevalue that
10284                         // would normally be baked into the lightmap must be
10285                         // applied to the color
10286                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10287                         if (model->type == mod_brushq3)
10288                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10289                         colorscale *= r_refdef.lightmapintensity;
10290                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10291                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10292                         // basic lit geometry
10293                         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]);
10294                         // add pants/shirt if needed
10295                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10296                                 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]);
10297                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10298                                 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]);
10299                         // now add ambient passes if needed
10300                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10301                         {
10302                                 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]);
10303                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10304                                         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]);
10305                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10306                                         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]);
10307                         }
10308                 }
10309                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10310                         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]);
10311                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10312                 {
10313                         // if this is opaque use alpha blend which will darken the earlier
10314                         // passes cheaply.
10315                         //
10316                         // if this is an alpha blended material, all the earlier passes
10317                         // were darkened by fog already, so we only need to add the fog
10318                         // color ontop through the fog mask texture
10319                         //
10320                         // if this is an additive blended material, all the earlier passes
10321                         // were darkened by fog already, and we should not add fog color
10322                         // (because the background was not darkened, there is no fog color
10323                         // that was lost behind it).
10324                         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]);
10325                 }
10326         }
10327
10328         return t->currentframe;
10329 }
10330
10331 rsurfacestate_t rsurface;
10332
10333 void RSurf_ActiveWorldEntity(void)
10334 {
10335         dp_model_t *model = r_refdef.scene.worldmodel;
10336         //if (rsurface.entity == r_refdef.scene.worldentity)
10337         //      return;
10338         rsurface.entity = r_refdef.scene.worldentity;
10339         rsurface.skeleton = NULL;
10340         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10341         rsurface.ent_skinnum = 0;
10342         rsurface.ent_qwskin = -1;
10343         rsurface.ent_shadertime = 0;
10344         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10345         rsurface.matrix = identitymatrix;
10346         rsurface.inversematrix = identitymatrix;
10347         rsurface.matrixscale = 1;
10348         rsurface.inversematrixscale = 1;
10349         R_EntityMatrix(&identitymatrix);
10350         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10351         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10352         rsurface.fograngerecip = r_refdef.fograngerecip;
10353         rsurface.fogheightfade = r_refdef.fogheightfade;
10354         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10355         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10356         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10357         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10358         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10359         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10360         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10361         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10362         rsurface.colormod[3] = 1;
10363         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);
10364         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10365         rsurface.frameblend[0].lerp = 1;
10366         rsurface.ent_alttextures = false;
10367         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10368         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10369         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10370         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10371         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10372         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10373         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10374         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10375         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10376         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10377         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10378         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10379         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10380         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10381         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10382         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10383         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10384         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10385         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10386         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10387         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10388         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10389         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10390         rsurface.modelelement3i = model->surfmesh.data_element3i;
10391         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10392         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10393         rsurface.modelelement3s = model->surfmesh.data_element3s;
10394         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10395         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10396         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10397         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10398         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10399         rsurface.modelsurfaces = model->data_surfaces;
10400         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10401         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10402         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10403         rsurface.modelgeneratedvertex = false;
10404         rsurface.batchgeneratedvertex = false;
10405         rsurface.batchfirstvertex = 0;
10406         rsurface.batchnumvertices = 0;
10407         rsurface.batchfirsttriangle = 0;
10408         rsurface.batchnumtriangles = 0;
10409         rsurface.batchvertex3f  = NULL;
10410         rsurface.batchvertex3f_vertexbuffer = NULL;
10411         rsurface.batchvertex3f_bufferoffset = 0;
10412         rsurface.batchsvector3f = NULL;
10413         rsurface.batchsvector3f_vertexbuffer = NULL;
10414         rsurface.batchsvector3f_bufferoffset = 0;
10415         rsurface.batchtvector3f = NULL;
10416         rsurface.batchtvector3f_vertexbuffer = NULL;
10417         rsurface.batchtvector3f_bufferoffset = 0;
10418         rsurface.batchnormal3f  = NULL;
10419         rsurface.batchnormal3f_vertexbuffer = NULL;
10420         rsurface.batchnormal3f_bufferoffset = 0;
10421         rsurface.batchlightmapcolor4f = NULL;
10422         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10423         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10424         rsurface.batchtexcoordtexture2f = NULL;
10425         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10426         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10427         rsurface.batchtexcoordlightmap2f = NULL;
10428         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10429         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10430         rsurface.batchvertexmesh = NULL;
10431         rsurface.batchvertexmeshbuffer = NULL;
10432         rsurface.batchvertex3fbuffer = NULL;
10433         rsurface.batchelement3i = NULL;
10434         rsurface.batchelement3i_indexbuffer = NULL;
10435         rsurface.batchelement3i_bufferoffset = 0;
10436         rsurface.batchelement3s = NULL;
10437         rsurface.batchelement3s_indexbuffer = NULL;
10438         rsurface.batchelement3s_bufferoffset = 0;
10439         rsurface.passcolor4f = NULL;
10440         rsurface.passcolor4f_vertexbuffer = NULL;
10441         rsurface.passcolor4f_bufferoffset = 0;
10442 }
10443
10444 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10445 {
10446         dp_model_t *model = ent->model;
10447         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10448         //      return;
10449         rsurface.entity = (entity_render_t *)ent;
10450         rsurface.skeleton = ent->skeleton;
10451         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10452         rsurface.ent_skinnum = ent->skinnum;
10453         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;
10454         rsurface.ent_shadertime = ent->shadertime;
10455         rsurface.ent_flags = ent->flags;
10456         rsurface.matrix = ent->matrix;
10457         rsurface.inversematrix = ent->inversematrix;
10458         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10459         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10460         R_EntityMatrix(&rsurface.matrix);
10461         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10462         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10463         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10464         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10465         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10466         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10467         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10468         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10469         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10470         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10471         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10472         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10473         rsurface.colormod[3] = ent->alpha;
10474         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10475         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10476         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10477         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10478         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10479         if (ent->model->brush.submodel && !prepass)
10480         {
10481                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10482                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10483         }
10484         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10485         {
10486                 if (ent->animcache_vertex3f)
10487                 {
10488                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10489                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10490                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10491                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10492                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10493                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10494                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
10495                 }
10496                 else if (wanttangents)
10497                 {
10498                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10499                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10500                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10501                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10502                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
10503                         rsurface.modelvertexmesh = NULL;
10504                         rsurface.modelvertexmeshbuffer = NULL;
10505                         rsurface.modelvertex3fbuffer = NULL;
10506                 }
10507                 else if (wantnormals)
10508                 {
10509                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10510                         rsurface.modelsvector3f = NULL;
10511                         rsurface.modeltvector3f = NULL;
10512                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10513                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
10514                         rsurface.modelvertexmesh = NULL;
10515                         rsurface.modelvertexmeshbuffer = NULL;
10516                         rsurface.modelvertex3fbuffer = NULL;
10517                 }
10518                 else
10519                 {
10520                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10521                         rsurface.modelsvector3f = NULL;
10522                         rsurface.modeltvector3f = NULL;
10523                         rsurface.modelnormal3f = NULL;
10524                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
10525                         rsurface.modelvertexmesh = NULL;
10526                         rsurface.modelvertexmeshbuffer = NULL;
10527                         rsurface.modelvertex3fbuffer = NULL;
10528                 }
10529                 rsurface.modelvertex3f_vertexbuffer = 0;
10530                 rsurface.modelvertex3f_bufferoffset = 0;
10531                 rsurface.modelsvector3f_vertexbuffer = 0;
10532                 rsurface.modelsvector3f_bufferoffset = 0;
10533                 rsurface.modeltvector3f_vertexbuffer = 0;
10534                 rsurface.modeltvector3f_bufferoffset = 0;
10535                 rsurface.modelnormal3f_vertexbuffer = 0;
10536                 rsurface.modelnormal3f_bufferoffset = 0;
10537                 rsurface.modelgeneratedvertex = true;
10538         }
10539         else
10540         {
10541                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10542                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10543                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10544                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10545                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10546                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10547                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10548                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10549                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10550                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10551                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10552                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10553                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10554                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10555                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10556                 rsurface.modelgeneratedvertex = false;
10557         }
10558         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10559         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10560         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10561         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10562         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10563         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10564         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10565         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10566         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10567         rsurface.modelelement3i = model->surfmesh.data_element3i;
10568         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10569         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10570         rsurface.modelelement3s = model->surfmesh.data_element3s;
10571         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10572         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10573         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10574         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10575         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10576         rsurface.modelsurfaces = model->data_surfaces;
10577         rsurface.batchgeneratedvertex = false;
10578         rsurface.batchfirstvertex = 0;
10579         rsurface.batchnumvertices = 0;
10580         rsurface.batchfirsttriangle = 0;
10581         rsurface.batchnumtriangles = 0;
10582         rsurface.batchvertex3f  = NULL;
10583         rsurface.batchvertex3f_vertexbuffer = NULL;
10584         rsurface.batchvertex3f_bufferoffset = 0;
10585         rsurface.batchsvector3f = NULL;
10586         rsurface.batchsvector3f_vertexbuffer = NULL;
10587         rsurface.batchsvector3f_bufferoffset = 0;
10588         rsurface.batchtvector3f = NULL;
10589         rsurface.batchtvector3f_vertexbuffer = NULL;
10590         rsurface.batchtvector3f_bufferoffset = 0;
10591         rsurface.batchnormal3f  = NULL;
10592         rsurface.batchnormal3f_vertexbuffer = NULL;
10593         rsurface.batchnormal3f_bufferoffset = 0;
10594         rsurface.batchlightmapcolor4f = NULL;
10595         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10596         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10597         rsurface.batchtexcoordtexture2f = NULL;
10598         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10599         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10600         rsurface.batchtexcoordlightmap2f = NULL;
10601         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10602         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10603         rsurface.batchvertexmesh = NULL;
10604         rsurface.batchvertexmeshbuffer = NULL;
10605         rsurface.batchvertex3fbuffer = NULL;
10606         rsurface.batchelement3i = NULL;
10607         rsurface.batchelement3i_indexbuffer = NULL;
10608         rsurface.batchelement3i_bufferoffset = 0;
10609         rsurface.batchelement3s = NULL;
10610         rsurface.batchelement3s_indexbuffer = NULL;
10611         rsurface.batchelement3s_bufferoffset = 0;
10612         rsurface.passcolor4f = NULL;
10613         rsurface.passcolor4f_vertexbuffer = NULL;
10614         rsurface.passcolor4f_bufferoffset = 0;
10615 }
10616
10617 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)
10618 {
10619         rsurface.entity = r_refdef.scene.worldentity;
10620         rsurface.skeleton = NULL;
10621         rsurface.ent_skinnum = 0;
10622         rsurface.ent_qwskin = -1;
10623         rsurface.ent_shadertime = shadertime;
10624         rsurface.ent_flags = entflags;
10625         rsurface.modelnumvertices = numvertices;
10626         rsurface.modelnumtriangles = numtriangles;
10627         rsurface.matrix = *matrix;
10628         rsurface.inversematrix = *inversematrix;
10629         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10630         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10631         R_EntityMatrix(&rsurface.matrix);
10632         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10633         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10634         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10635         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10636         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10637         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10638         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10639         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10640         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10641         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10642         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10643         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10644         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);
10645         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10646         rsurface.frameblend[0].lerp = 1;
10647         rsurface.ent_alttextures = false;
10648         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10649         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10650         if (wanttangents)
10651         {
10652                 rsurface.modelvertex3f = (float *)vertex3f;
10653                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10654                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10655                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10656         }
10657         else if (wantnormals)
10658         {
10659                 rsurface.modelvertex3f = (float *)vertex3f;
10660                 rsurface.modelsvector3f = NULL;
10661                 rsurface.modeltvector3f = NULL;
10662                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10663         }
10664         else
10665         {
10666                 rsurface.modelvertex3f = (float *)vertex3f;
10667                 rsurface.modelsvector3f = NULL;
10668                 rsurface.modeltvector3f = NULL;
10669                 rsurface.modelnormal3f = NULL;
10670         }
10671         rsurface.modelvertexmesh = NULL;
10672         rsurface.modelvertexmeshbuffer = NULL;
10673         rsurface.modelvertex3fbuffer = NULL;
10674         rsurface.modelvertex3f_vertexbuffer = 0;
10675         rsurface.modelvertex3f_bufferoffset = 0;
10676         rsurface.modelsvector3f_vertexbuffer = 0;
10677         rsurface.modelsvector3f_bufferoffset = 0;
10678         rsurface.modeltvector3f_vertexbuffer = 0;
10679         rsurface.modeltvector3f_bufferoffset = 0;
10680         rsurface.modelnormal3f_vertexbuffer = 0;
10681         rsurface.modelnormal3f_bufferoffset = 0;
10682         rsurface.modelgeneratedvertex = true;
10683         rsurface.modellightmapcolor4f  = (float *)color4f;
10684         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10685         rsurface.modellightmapcolor4f_bufferoffset = 0;
10686         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
10687         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10688         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10689         rsurface.modeltexcoordlightmap2f  = NULL;
10690         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10691         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10692         rsurface.modelelement3i = (int *)element3i;
10693         rsurface.modelelement3i_indexbuffer = NULL;
10694         rsurface.modelelement3i_bufferoffset = 0;
10695         rsurface.modelelement3s = (unsigned short *)element3s;
10696         rsurface.modelelement3s_indexbuffer = NULL;
10697         rsurface.modelelement3s_bufferoffset = 0;
10698         rsurface.modellightmapoffsets = NULL;
10699         rsurface.modelsurfaces = NULL;
10700         rsurface.batchgeneratedvertex = false;
10701         rsurface.batchfirstvertex = 0;
10702         rsurface.batchnumvertices = 0;
10703         rsurface.batchfirsttriangle = 0;
10704         rsurface.batchnumtriangles = 0;
10705         rsurface.batchvertex3f  = NULL;
10706         rsurface.batchvertex3f_vertexbuffer = NULL;
10707         rsurface.batchvertex3f_bufferoffset = 0;
10708         rsurface.batchsvector3f = NULL;
10709         rsurface.batchsvector3f_vertexbuffer = NULL;
10710         rsurface.batchsvector3f_bufferoffset = 0;
10711         rsurface.batchtvector3f = NULL;
10712         rsurface.batchtvector3f_vertexbuffer = NULL;
10713         rsurface.batchtvector3f_bufferoffset = 0;
10714         rsurface.batchnormal3f  = NULL;
10715         rsurface.batchnormal3f_vertexbuffer = NULL;
10716         rsurface.batchnormal3f_bufferoffset = 0;
10717         rsurface.batchlightmapcolor4f = NULL;
10718         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10719         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10720         rsurface.batchtexcoordtexture2f = NULL;
10721         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10722         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10723         rsurface.batchtexcoordlightmap2f = NULL;
10724         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10725         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10726         rsurface.batchvertexmesh = NULL;
10727         rsurface.batchvertexmeshbuffer = NULL;
10728         rsurface.batchvertex3fbuffer = NULL;
10729         rsurface.batchelement3i = NULL;
10730         rsurface.batchelement3i_indexbuffer = NULL;
10731         rsurface.batchelement3i_bufferoffset = 0;
10732         rsurface.batchelement3s = NULL;
10733         rsurface.batchelement3s_indexbuffer = NULL;
10734         rsurface.batchelement3s_bufferoffset = 0;
10735         rsurface.passcolor4f = NULL;
10736         rsurface.passcolor4f_vertexbuffer = NULL;
10737         rsurface.passcolor4f_bufferoffset = 0;
10738
10739         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10740         {
10741                 if ((wantnormals || wanttangents) && !normal3f)
10742                 {
10743                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10744                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10745                 }
10746                 if (wanttangents && !svector3f)
10747                 {
10748                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10749                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10750                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10751                 }
10752         }
10753 }
10754
10755 float RSurf_FogPoint(const float *v)
10756 {
10757         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10758         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10759         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10760         float FogHeightFade = r_refdef.fogheightfade;
10761         float fogfrac;
10762         unsigned int fogmasktableindex;
10763         if (r_refdef.fogplaneviewabove)
10764                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10765         else
10766                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10767         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10768         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10769 }
10770
10771 float RSurf_FogVertex(const float *v)
10772 {
10773         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10774         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10775         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10776         float FogHeightFade = rsurface.fogheightfade;
10777         float fogfrac;
10778         unsigned int fogmasktableindex;
10779         if (r_refdef.fogplaneviewabove)
10780                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10781         else
10782                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10783         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10784         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10785 }
10786
10787 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10788 {
10789         int i;
10790         for (i = 0;i < numelements;i++)
10791                 outelement3i[i] = inelement3i[i] + adjust;
10792 }
10793
10794 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10795 extern cvar_t gl_vbo;
10796 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10797 {
10798         int deformindex;
10799         int firsttriangle;
10800         int numtriangles;
10801         int firstvertex;
10802         int endvertex;
10803         int numvertices;
10804         int surfacefirsttriangle;
10805         int surfacenumtriangles;
10806         int surfacefirstvertex;
10807         int surfaceendvertex;
10808         int surfacenumvertices;
10809         int batchnumvertices;
10810         int batchnumtriangles;
10811         int needsupdate;
10812         int i, j;
10813         qboolean gaps;
10814         qboolean dynamicvertex;
10815         float amplitude;
10816         float animpos;
10817         float scale;
10818         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10819         float waveparms[4];
10820         q3shaderinfo_deform_t *deform;
10821         const msurface_t *surface, *firstsurface;
10822         r_vertexmesh_t *vertexmesh;
10823         if (!texturenumsurfaces)
10824                 return;
10825         // find vertex range of this surface batch
10826         gaps = false;
10827         firstsurface = texturesurfacelist[0];
10828         firsttriangle = firstsurface->num_firsttriangle;
10829         batchnumvertices = 0;
10830         batchnumtriangles = 0;
10831         firstvertex = endvertex = firstsurface->num_firstvertex;
10832         for (i = 0;i < texturenumsurfaces;i++)
10833         {
10834                 surface = texturesurfacelist[i];
10835                 if (surface != firstsurface + i)
10836                         gaps = true;
10837                 surfacefirstvertex = surface->num_firstvertex;
10838                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10839                 surfacenumvertices = surface->num_vertices;
10840                 surfacenumtriangles = surface->num_triangles;
10841                 if (firstvertex > surfacefirstvertex)
10842                         firstvertex = surfacefirstvertex;
10843                 if (endvertex < surfaceendvertex)
10844                         endvertex = surfaceendvertex;
10845                 batchnumvertices += surfacenumvertices;
10846                 batchnumtriangles += surfacenumtriangles;
10847         }
10848
10849         // we now know the vertex range used, and if there are any gaps in it
10850         rsurface.batchfirstvertex = firstvertex;
10851         rsurface.batchnumvertices = endvertex - firstvertex;
10852         rsurface.batchfirsttriangle = firsttriangle;
10853         rsurface.batchnumtriangles = batchnumtriangles;
10854
10855         // this variable holds flags for which properties have been updated that
10856         // may require regenerating vertexmesh array...
10857         needsupdate = 0;
10858
10859         // check if any dynamic vertex processing must occur
10860         dynamicvertex = false;
10861
10862         // if there is a chance of animated vertex colors, it's a dynamic batch
10863         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10864         {
10865                 dynamicvertex = true;
10866                 batchneed |= BATCHNEED_NOGAPS;
10867                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
10868         }
10869
10870         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10871         {
10872                 switch (deform->deform)
10873                 {
10874                 default:
10875                 case Q3DEFORM_PROJECTIONSHADOW:
10876                 case Q3DEFORM_TEXT0:
10877                 case Q3DEFORM_TEXT1:
10878                 case Q3DEFORM_TEXT2:
10879                 case Q3DEFORM_TEXT3:
10880                 case Q3DEFORM_TEXT4:
10881                 case Q3DEFORM_TEXT5:
10882                 case Q3DEFORM_TEXT6:
10883                 case Q3DEFORM_TEXT7:
10884                 case Q3DEFORM_NONE:
10885                         break;
10886                 case Q3DEFORM_AUTOSPRITE:
10887                         dynamicvertex = true;
10888                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10889                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10890                         break;
10891                 case Q3DEFORM_AUTOSPRITE2:
10892                         dynamicvertex = true;
10893                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10894                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10895                         break;
10896                 case Q3DEFORM_NORMAL:
10897                         dynamicvertex = true;
10898                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10899                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10900                         break;
10901                 case Q3DEFORM_WAVE:
10902                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10903                                 break; // if wavefunc is a nop, ignore this transform
10904                         dynamicvertex = true;
10905                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10906                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10907                         break;
10908                 case Q3DEFORM_BULGE:
10909                         dynamicvertex = true;
10910                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10911                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10912                         break;
10913                 case Q3DEFORM_MOVE:
10914                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10915                                 break; // if wavefunc is a nop, ignore this transform
10916                         dynamicvertex = true;
10917                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10918                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
10919                         break;
10920                 }
10921         }
10922         switch(rsurface.texture->tcgen.tcgen)
10923         {
10924         default:
10925         case Q3TCGEN_TEXTURE:
10926                 break;
10927         case Q3TCGEN_LIGHTMAP:
10928                 dynamicvertex = true;
10929                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10930                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10931                 break;
10932         case Q3TCGEN_VECTOR:
10933                 dynamicvertex = true;
10934                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10935                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10936                 break;
10937         case Q3TCGEN_ENVIRONMENT:
10938                 dynamicvertex = true;
10939                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
10940                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10941                 break;
10942         }
10943         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10944         {
10945                 dynamicvertex = true;
10946                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10947                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10948         }
10949
10950         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10951         {
10952                 dynamicvertex = true;
10953                 batchneed |= BATCHNEED_NOGAPS;
10954                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
10955         }
10956
10957         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
10958         {
10959                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
10960                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
10961                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
10962                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
10963                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
10964                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
10965                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
10966         }
10967
10968         // when the model data has no vertex buffer (dynamic mesh), we need to
10969         // eliminate gaps
10970         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
10971                 batchneed |= BATCHNEED_NOGAPS;
10972
10973         // if needsupdate, we have to do a dynamic vertex batch for sure
10974         if (needsupdate & batchneed)
10975                 dynamicvertex = true;
10976
10977         // see if we need to build vertexmesh from arrays
10978         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10979                 dynamicvertex = true;
10980
10981         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
10982         // also some drivers strongly dislike firstvertex
10983         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
10984                 dynamicvertex = true;
10985
10986         rsurface.batchvertex3f = rsurface.modelvertex3f;
10987         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
10988         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10989         rsurface.batchsvector3f = rsurface.modelsvector3f;
10990         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
10991         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10992         rsurface.batchtvector3f = rsurface.modeltvector3f;
10993         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
10994         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10995         rsurface.batchnormal3f = rsurface.modelnormal3f;
10996         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
10997         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10998         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
10999         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11000         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11001         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11002         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11003         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11004         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11005         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11006         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11007         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11008         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11009         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11010         rsurface.batchelement3i = rsurface.modelelement3i;
11011         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11012         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11013         rsurface.batchelement3s = rsurface.modelelement3s;
11014         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11015         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11016
11017         // if any dynamic vertex processing has to occur in software, we copy the
11018         // entire surface list together before processing to rebase the vertices
11019         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11020         //
11021         // if any gaps exist and we do not have a static vertex buffer, we have to
11022         // copy the surface list together to avoid wasting upload bandwidth on the
11023         // vertices in the gaps.
11024         //
11025         // if gaps exist and we have a static vertex buffer, we still have to
11026         // combine the index buffer ranges into one dynamic index buffer.
11027         //
11028         // in all cases we end up with data that can be drawn in one call.
11029
11030         if (!dynamicvertex)
11031         {
11032                 // static vertex data, just set pointers...
11033                 rsurface.batchgeneratedvertex = false;
11034                 // if there are gaps, we want to build a combined index buffer,
11035                 // otherwise use the original static buffer with an appropriate offset
11036                 if (gaps)
11037                 {
11038                         // build a new triangle elements array for this batch
11039                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11040                         rsurface.batchfirsttriangle = 0;
11041                         numtriangles = 0;
11042                         for (i = 0;i < texturenumsurfaces;i++)
11043                         {
11044                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11045                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11046                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11047                                 numtriangles += surfacenumtriangles;
11048                         }
11049                         rsurface.batchelement3i_indexbuffer = NULL;
11050                         rsurface.batchelement3i_bufferoffset = 0;
11051                         rsurface.batchelement3s = NULL;
11052                         rsurface.batchelement3s_indexbuffer = NULL;
11053                         rsurface.batchelement3s_bufferoffset = 0;
11054                         if (endvertex <= 65536)
11055                         {
11056                                 // make a 16bit (unsigned short) index array if possible
11057                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11058                                 for (i = 0;i < numtriangles*3;i++)
11059                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11060                         }
11061                 }
11062                 return;
11063         }
11064
11065         // something needs software processing, do it for real...
11066         // we only directly handle separate array data in this case and then
11067         // generate interleaved data if needed...
11068         rsurface.batchgeneratedvertex = true;
11069
11070         // now copy the vertex data into a combined array and make an index array
11071         // (this is what Quake3 does all the time)
11072         //if (gaps || rsurface.batchfirstvertex)
11073         {
11074                 rsurface.batchvertex3fbuffer = NULL;
11075                 rsurface.batchvertexmesh = NULL;
11076                 rsurface.batchvertexmeshbuffer = NULL;
11077                 rsurface.batchvertex3f = NULL;
11078                 rsurface.batchvertex3f_vertexbuffer = NULL;
11079                 rsurface.batchvertex3f_bufferoffset = 0;
11080                 rsurface.batchsvector3f = NULL;
11081                 rsurface.batchsvector3f_vertexbuffer = NULL;
11082                 rsurface.batchsvector3f_bufferoffset = 0;
11083                 rsurface.batchtvector3f = NULL;
11084                 rsurface.batchtvector3f_vertexbuffer = NULL;
11085                 rsurface.batchtvector3f_bufferoffset = 0;
11086                 rsurface.batchnormal3f = NULL;
11087                 rsurface.batchnormal3f_vertexbuffer = NULL;
11088                 rsurface.batchnormal3f_bufferoffset = 0;
11089                 rsurface.batchlightmapcolor4f = NULL;
11090                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11091                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11092                 rsurface.batchtexcoordtexture2f = NULL;
11093                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11094                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11095                 rsurface.batchtexcoordlightmap2f = NULL;
11096                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11097                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11098                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11099                 rsurface.batchelement3i_indexbuffer = NULL;
11100                 rsurface.batchelement3i_bufferoffset = 0;
11101                 rsurface.batchelement3s = NULL;
11102                 rsurface.batchelement3s_indexbuffer = NULL;
11103                 rsurface.batchelement3s_bufferoffset = 0;
11104                 // we'll only be setting up certain arrays as needed
11105                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11106                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11107                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11108                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11109                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11110                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11111                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11112                 {
11113                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11114                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11115                 }
11116                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11117                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11118                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11119                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11120                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11121                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11122                 numvertices = 0;
11123                 numtriangles = 0;
11124                 for (i = 0;i < texturenumsurfaces;i++)
11125                 {
11126                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11127                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11128                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11129                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11130                         // copy only the data requested
11131                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11132                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11133                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11134                         {
11135                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11136                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11137                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11138                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11139                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11140                                 {
11141                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11142                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11143                                 }
11144                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11145                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11146                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11147                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11148                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11149                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11150                         }
11151                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11152                         numvertices += surfacenumvertices;
11153                         numtriangles += surfacenumtriangles;
11154                 }
11155
11156                 // generate a 16bit index array as well if possible
11157                 // (in general, dynamic batches fit)
11158                 if (numvertices <= 65536)
11159                 {
11160                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11161                         for (i = 0;i < numtriangles*3;i++)
11162                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11163                 }
11164
11165                 // since we've copied everything, the batch now starts at 0
11166                 rsurface.batchfirstvertex = 0;
11167                 rsurface.batchnumvertices = batchnumvertices;
11168                 rsurface.batchfirsttriangle = 0;
11169                 rsurface.batchnumtriangles = batchnumtriangles;
11170         }
11171
11172         // q1bsp surfaces rendered in vertex color mode have to have colors
11173         // calculated based on lightstyles
11174         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11175         {
11176                 // generate color arrays for the surfaces in this list
11177                 int c[4];
11178                 int scale;
11179                 int size3;
11180                 const int *offsets;
11181                 const unsigned char *lm;
11182                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11183                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11184                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11185                 numvertices = 0;
11186                 for (i = 0;i < texturenumsurfaces;i++)
11187                 {
11188                         surface = texturesurfacelist[i];
11189                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11190                         surfacenumvertices = surface->num_vertices;
11191                         if (surface->lightmapinfo->samples)
11192                         {
11193                                 for (j = 0;j < surfacenumvertices;j++)
11194                                 {
11195                                         lm = surface->lightmapinfo->samples + offsets[j];
11196                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11197                                         VectorScale(lm, scale, c);
11198                                         if (surface->lightmapinfo->styles[1] != 255)
11199                                         {
11200                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11201                                                 lm += size3;
11202                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11203                                                 VectorMA(c, scale, lm, c);
11204                                                 if (surface->lightmapinfo->styles[2] != 255)
11205                                                 {
11206                                                         lm += size3;
11207                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11208                                                         VectorMA(c, scale, lm, c);
11209                                                         if (surface->lightmapinfo->styles[3] != 255)
11210                                                         {
11211                                                                 lm += size3;
11212                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11213                                                                 VectorMA(c, scale, lm, c);
11214                                                         }
11215                                                 }
11216                                         }
11217                                         c[0] >>= 7;
11218                                         c[1] >>= 7;
11219                                         c[2] >>= 7;
11220                                         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);
11221                                         numvertices++;
11222                                 }
11223                         }
11224                         else
11225                         {
11226                                 for (j = 0;j < surfacenumvertices;j++)
11227                                 {
11228                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11229                                         numvertices++;
11230                                 }
11231                         }
11232                 }
11233         }
11234
11235         // if vertices are deformed (sprite flares and things in maps, possibly
11236         // water waves, bulges and other deformations), modify the copied vertices
11237         // in place
11238         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11239         {
11240                 switch (deform->deform)
11241                 {
11242                 default:
11243                 case Q3DEFORM_PROJECTIONSHADOW:
11244                 case Q3DEFORM_TEXT0:
11245                 case Q3DEFORM_TEXT1:
11246                 case Q3DEFORM_TEXT2:
11247                 case Q3DEFORM_TEXT3:
11248                 case Q3DEFORM_TEXT4:
11249                 case Q3DEFORM_TEXT5:
11250                 case Q3DEFORM_TEXT6:
11251                 case Q3DEFORM_TEXT7:
11252                 case Q3DEFORM_NONE:
11253                         break;
11254                 case Q3DEFORM_AUTOSPRITE:
11255                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11256                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11257                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11258                         VectorNormalize(newforward);
11259                         VectorNormalize(newright);
11260                         VectorNormalize(newup);
11261 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11262 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11263 //                      rsurface.batchvertex3f_bufferoffset = 0;
11264 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11265 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
11266 //                      rsurface.batchsvector3f_bufferoffset = 0;
11267 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11268 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
11269 //                      rsurface.batchtvector3f_bufferoffset = 0;
11270 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11271 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11272 //                      rsurface.batchnormal3f_bufferoffset = 0;
11273                         // a single autosprite surface can contain multiple sprites...
11274                         for (j = 0;j < batchnumvertices - 3;j += 4)
11275                         {
11276                                 VectorClear(center);
11277                                 for (i = 0;i < 4;i++)
11278                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11279                                 VectorScale(center, 0.25f, center);
11280                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11281                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11282                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11283                                 for (i = 0;i < 4;i++)
11284                                 {
11285                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11286                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11287                                 }
11288                         }
11289                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11290                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11291                         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);
11292                         break;
11293                 case Q3DEFORM_AUTOSPRITE2:
11294                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11295                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11296                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11297                         VectorNormalize(newforward);
11298                         VectorNormalize(newright);
11299                         VectorNormalize(newup);
11300 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11301 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11302 //                      rsurface.batchvertex3f_bufferoffset = 0;
11303                         {
11304                                 const float *v1, *v2;
11305                                 vec3_t start, end;
11306                                 float f, l;
11307                                 struct
11308                                 {
11309                                         float length2;
11310                                         const float *v1;
11311                                         const float *v2;
11312                                 }
11313                                 shortest[2];
11314                                 memset(shortest, 0, sizeof(shortest));
11315                                 // a single autosprite surface can contain multiple sprites...
11316                                 for (j = 0;j < batchnumvertices - 3;j += 4)
11317                                 {
11318                                         VectorClear(center);
11319                                         for (i = 0;i < 4;i++)
11320                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11321                                         VectorScale(center, 0.25f, center);
11322                                         // find the two shortest edges, then use them to define the
11323                                         // axis vectors for rotating around the central axis
11324                                         for (i = 0;i < 6;i++)
11325                                         {
11326                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11327                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11328                                                 l = VectorDistance2(v1, v2);
11329                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11330                                                 if (v1[2] != v2[2])
11331                                                         l += (1.0f / 1024.0f);
11332                                                 if (shortest[0].length2 > l || i == 0)
11333                                                 {
11334                                                         shortest[1] = shortest[0];
11335                                                         shortest[0].length2 = l;
11336                                                         shortest[0].v1 = v1;
11337                                                         shortest[0].v2 = v2;
11338                                                 }
11339                                                 else if (shortest[1].length2 > l || i == 1)
11340                                                 {
11341                                                         shortest[1].length2 = l;
11342                                                         shortest[1].v1 = v1;
11343                                                         shortest[1].v2 = v2;
11344                                                 }
11345                                         }
11346                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11347                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11348                                         // this calculates the right vector from the shortest edge
11349                                         // and the up vector from the edge midpoints
11350                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11351                                         VectorNormalize(right);
11352                                         VectorSubtract(end, start, up);
11353                                         VectorNormalize(up);
11354                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11355                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11356                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11357                                         VectorNegate(forward, forward);
11358                                         VectorReflect(forward, 0, up, forward);
11359                                         VectorNormalize(forward);
11360                                         CrossProduct(up, forward, newright);
11361                                         VectorNormalize(newright);
11362                                         // rotate the quad around the up axis vector, this is made
11363                                         // especially easy by the fact we know the quad is flat,
11364                                         // so we only have to subtract the center position and
11365                                         // measure distance along the right vector, and then
11366                                         // multiply that by the newright vector and add back the
11367                                         // center position
11368                                         // we also need to subtract the old position to undo the
11369                                         // displacement from the center, which we do with a
11370                                         // DotProduct, the subtraction/addition of center is also
11371                                         // optimized into DotProducts here
11372                                         l = DotProduct(right, center);
11373                                         for (i = 0;i < 4;i++)
11374                                         {
11375                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11376                                                 f = DotProduct(right, v1) - l;
11377                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11378                                         }
11379                                 }
11380                         }
11381                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11382                         {
11383 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11384 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
11385 //                              rsurface.batchnormal3f_bufferoffset = 0;
11386                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11387                         }
11388                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11389                         {
11390 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11391 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11392 //                              rsurface.batchsvector3f_bufferoffset = 0;
11393 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11394 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11395 //                              rsurface.batchtvector3f_bufferoffset = 0;
11396                                 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);
11397                         }
11398                         break;
11399                 case Q3DEFORM_NORMAL:
11400                         // deform the normals to make reflections wavey
11401                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11402                         rsurface.batchnormal3f_vertexbuffer = NULL;
11403                         rsurface.batchnormal3f_bufferoffset = 0;
11404                         for (j = 0;j < batchnumvertices;j++)
11405                         {
11406                                 float vertex[3];
11407                                 float *normal = rsurface.batchnormal3f + 3*j;
11408                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11409                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11410                                 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]);
11411                                 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]);
11412                                 VectorNormalize(normal);
11413                         }
11414                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11415                         {
11416 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11417 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11418 //                              rsurface.batchsvector3f_bufferoffset = 0;
11419 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11420 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11421 //                              rsurface.batchtvector3f_bufferoffset = 0;
11422                                 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);
11423                         }
11424                         break;
11425                 case Q3DEFORM_WAVE:
11426                         // deform vertex array to make wavey water and flags and such
11427                         waveparms[0] = deform->waveparms[0];
11428                         waveparms[1] = deform->waveparms[1];
11429                         waveparms[2] = deform->waveparms[2];
11430                         waveparms[3] = deform->waveparms[3];
11431                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11432                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11433                         // this is how a divisor of vertex influence on deformation
11434                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11435                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11436 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11437 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11438 //                      rsurface.batchvertex3f_bufferoffset = 0;
11439 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11440 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11441 //                      rsurface.batchnormal3f_bufferoffset = 0;
11442                         for (j = 0;j < batchnumvertices;j++)
11443                         {
11444                                 // if the wavefunc depends on time, evaluate it per-vertex
11445                                 if (waveparms[3])
11446                                 {
11447                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11448                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11449                                 }
11450                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11451                         }
11452                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11453                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11454                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11455                         {
11456 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11457 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11458 //                              rsurface.batchsvector3f_bufferoffset = 0;
11459 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11460 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11461 //                              rsurface.batchtvector3f_bufferoffset = 0;
11462                                 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);
11463                         }
11464                         break;
11465                 case Q3DEFORM_BULGE:
11466                         // deform vertex array to make the surface have moving bulges
11467 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11468 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11469 //                      rsurface.batchvertex3f_bufferoffset = 0;
11470 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11471 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11472 //                      rsurface.batchnormal3f_bufferoffset = 0;
11473                         for (j = 0;j < batchnumvertices;j++)
11474                         {
11475                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11476                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11477                         }
11478                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11479                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11480                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11481                         {
11482 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11483 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11484 //                              rsurface.batchsvector3f_bufferoffset = 0;
11485 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11486 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11487 //                              rsurface.batchtvector3f_bufferoffset = 0;
11488                                 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);
11489                         }
11490                         break;
11491                 case Q3DEFORM_MOVE:
11492                         // deform vertex array
11493                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11494                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11495                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11496                         VectorScale(deform->parms, scale, waveparms);
11497 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11498 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11499 //                      rsurface.batchvertex3f_bufferoffset = 0;
11500                         for (j = 0;j < batchnumvertices;j++)
11501                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
11502                         break;
11503                 }
11504         }
11505
11506         // generate texcoords based on the chosen texcoord source
11507         switch(rsurface.texture->tcgen.tcgen)
11508         {
11509         default:
11510         case Q3TCGEN_TEXTURE:
11511                 break;
11512         case Q3TCGEN_LIGHTMAP:
11513 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11514 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11515 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11516                 if (rsurface.batchtexcoordlightmap2f)
11517                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
11518                 break;
11519         case Q3TCGEN_VECTOR:
11520 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11521 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11522 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11523                 for (j = 0;j < batchnumvertices;j++)
11524                 {
11525                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11526                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11527                 }
11528                 break;
11529         case Q3TCGEN_ENVIRONMENT:
11530                 // make environment reflections using a spheremap
11531                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11532                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11533                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11534                 for (j = 0;j < batchnumvertices;j++)
11535                 {
11536                         // identical to Q3A's method, but executed in worldspace so
11537                         // carried models can be shiny too
11538
11539                         float viewer[3], d, reflected[3], worldreflected[3];
11540
11541                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11542                         // VectorNormalize(viewer);
11543
11544                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11545
11546                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11547                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11548                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11549                         // note: this is proportinal to viewer, so we can normalize later
11550
11551                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11552                         VectorNormalize(worldreflected);
11553
11554                         // note: this sphere map only uses world x and z!
11555                         // so positive and negative y will LOOK THE SAME.
11556                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11557                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11558                 }
11559                 break;
11560         }
11561         // the only tcmod that needs software vertex processing is turbulent, so
11562         // check for it here and apply the changes if needed
11563         // and we only support that as the first one
11564         // (handling a mixture of turbulent and other tcmods would be problematic
11565         //  without punting it entirely to a software path)
11566         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11567         {
11568                 amplitude = rsurface.texture->tcmods[0].parms[1];
11569                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11570 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11571 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11572 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11573                 for (j = 0;j < batchnumvertices;j++)
11574                 {
11575                         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);
11576                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11577                 }
11578         }
11579
11580         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11581         {
11582                 // convert the modified arrays to vertex structs
11583 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11584 //              rsurface.batchvertexmeshbuffer = NULL;
11585                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11586                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11587                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11588                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11589                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11590                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11591                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11592                 {
11593                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11594                         {
11595                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11596                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11597                         }
11598                 }
11599                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11600                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11601                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
11602                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11603                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11604                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11605                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11606                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11607                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11608         }
11609 }
11610
11611 void RSurf_DrawBatch(void)
11612 {
11613         // sometimes a zero triangle surface (usually a degenerate patch) makes it
11614         // through the pipeline, killing it earlier in the pipeline would have
11615         // per-surface overhead rather than per-batch overhead, so it's best to
11616         // reject it here, before it hits glDraw.
11617         if (rsurface.batchnumtriangles == 0)
11618                 return;
11619 #if 0
11620         // batch debugging code
11621         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
11622         {
11623                 int i;
11624                 int j;
11625                 int c;
11626                 const int *e;
11627                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
11628                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
11629                 {
11630                         c = e[i];
11631                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
11632                         {
11633                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
11634                                 {
11635                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
11636                                                 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);
11637                                         break;
11638                                 }
11639                         }
11640                 }
11641         }
11642 #endif
11643         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);
11644 }
11645
11646 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11647 {
11648         // pick the closest matching water plane
11649         int planeindex, vertexindex, bestplaneindex = -1;
11650         float d, bestd;
11651         vec3_t vert;
11652         const float *v;
11653         r_waterstate_waterplane_t *p;
11654         qboolean prepared = false;
11655         bestd = 0;
11656         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11657         {
11658                 if(p->camera_entity != rsurface.texture->camera_entity)
11659                         continue;
11660                 d = 0;
11661                 if(!prepared)
11662                 {
11663                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11664                         prepared = true;
11665                         if(rsurface.batchnumvertices == 0)
11666                                 break;
11667                 }
11668                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11669                 {
11670                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11671                         d += fabs(PlaneDiff(vert, &p->plane));
11672                 }
11673                 if (bestd > d || bestplaneindex < 0)
11674                 {
11675                         bestd = d;
11676                         bestplaneindex = planeindex;
11677                 }
11678         }
11679         return bestplaneindex;
11680         // NOTE: this MAY return a totally unrelated water plane; we can ignore
11681         // this situation though, as it might be better to render single larger
11682         // batches with useless stuff (backface culled for example) than to
11683         // render multiple smaller batches
11684 }
11685
11686 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11687 {
11688         int i;
11689         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11690         rsurface.passcolor4f_vertexbuffer = 0;
11691         rsurface.passcolor4f_bufferoffset = 0;
11692         for (i = 0;i < rsurface.batchnumvertices;i++)
11693                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11694 }
11695
11696 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11697 {
11698         int i;
11699         float f;
11700         const float *v;
11701         const float *c;
11702         float *c2;
11703         if (rsurface.passcolor4f)
11704         {
11705                 // generate color arrays
11706                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11707                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11708                 rsurface.passcolor4f_vertexbuffer = 0;
11709                 rsurface.passcolor4f_bufferoffset = 0;
11710                 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)
11711                 {
11712                         f = RSurf_FogVertex(v);
11713                         c2[0] = c[0] * f;
11714                         c2[1] = c[1] * f;
11715                         c2[2] = c[2] * f;
11716                         c2[3] = c[3];
11717                 }
11718         }
11719         else
11720         {
11721                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11722                 rsurface.passcolor4f_vertexbuffer = 0;
11723                 rsurface.passcolor4f_bufferoffset = 0;
11724                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11725                 {
11726                         f = RSurf_FogVertex(v);
11727                         c2[0] = f;
11728                         c2[1] = f;
11729                         c2[2] = f;
11730                         c2[3] = 1;
11731                 }
11732         }
11733 }
11734
11735 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11736 {
11737         int i;
11738         float f;
11739         const float *v;
11740         const float *c;
11741         float *c2;
11742         if (!rsurface.passcolor4f)
11743                 return;
11744         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11745         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11746         rsurface.passcolor4f_vertexbuffer = 0;
11747         rsurface.passcolor4f_bufferoffset = 0;
11748         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)
11749         {
11750                 f = RSurf_FogVertex(v);
11751                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11752                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11753                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11754                 c2[3] = c[3];
11755         }
11756 }
11757
11758 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11759 {
11760         int i;
11761         const float *c;
11762         float *c2;
11763         if (!rsurface.passcolor4f)
11764                 return;
11765         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11766         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11767         rsurface.passcolor4f_vertexbuffer = 0;
11768         rsurface.passcolor4f_bufferoffset = 0;
11769         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11770         {
11771                 c2[0] = c[0] * r;
11772                 c2[1] = c[1] * g;
11773                 c2[2] = c[2] * b;
11774                 c2[3] = c[3] * a;
11775         }
11776 }
11777
11778 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11779 {
11780         int i;
11781         const float *c;
11782         float *c2;
11783         if (!rsurface.passcolor4f)
11784                 return;
11785         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11786         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11787         rsurface.passcolor4f_vertexbuffer = 0;
11788         rsurface.passcolor4f_bufferoffset = 0;
11789         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11790         {
11791                 c2[0] = c[0] + r_refdef.scene.ambient;
11792                 c2[1] = c[1] + r_refdef.scene.ambient;
11793                 c2[2] = c[2] + r_refdef.scene.ambient;
11794                 c2[3] = c[3];
11795         }
11796 }
11797
11798 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11799 {
11800         // TODO: optimize
11801         rsurface.passcolor4f = NULL;
11802         rsurface.passcolor4f_vertexbuffer = 0;
11803         rsurface.passcolor4f_bufferoffset = 0;
11804         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11805         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11806         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11807         GL_Color(r, g, b, a);
11808         R_Mesh_TexBind(0, rsurface.lightmaptexture);
11809         RSurf_DrawBatch();
11810 }
11811
11812 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11813 {
11814         // TODO: optimize applyfog && applycolor case
11815         // just apply fog if necessary, and tint the fog color array if necessary
11816         rsurface.passcolor4f = NULL;
11817         rsurface.passcolor4f_vertexbuffer = 0;
11818         rsurface.passcolor4f_bufferoffset = 0;
11819         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11820         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11821         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11822         GL_Color(r, g, b, a);
11823         RSurf_DrawBatch();
11824 }
11825
11826 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11827 {
11828         // TODO: optimize
11829         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11830         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11831         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11832         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11833         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11834         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11835         GL_Color(r, g, b, a);
11836         RSurf_DrawBatch();
11837 }
11838
11839 static void RSurf_DrawBatch_GL11_ClampColor(void)
11840 {
11841         int i;
11842         const float *c1;
11843         float *c2;
11844         if (!rsurface.passcolor4f)
11845                 return;
11846         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11847         {
11848                 c2[0] = bound(0.0f, c1[0], 1.0f);
11849                 c2[1] = bound(0.0f, c1[1], 1.0f);
11850                 c2[2] = bound(0.0f, c1[2], 1.0f);
11851                 c2[3] = bound(0.0f, c1[3], 1.0f);
11852         }
11853 }
11854
11855 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
11856 {
11857         int i;
11858         float f;
11859         const float *v;
11860         const float *n;
11861         float *c;
11862         //vec3_t eyedir;
11863
11864         // fake shading
11865         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11866         rsurface.passcolor4f_vertexbuffer = 0;
11867         rsurface.passcolor4f_bufferoffset = 0;
11868         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)
11869         {
11870                 f = -DotProduct(r_refdef.view.forward, n);
11871                 f = max(0, f);
11872                 f = f * 0.85 + 0.15; // work around so stuff won't get black
11873                 f *= r_refdef.lightmapintensity;
11874                 Vector4Set(c, f, f, f, 1);
11875         }
11876 }
11877
11878 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11879 {
11880         RSurf_DrawBatch_GL11_ApplyFakeLight();
11881         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11882         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11883         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11884         GL_Color(r, g, b, a);
11885         RSurf_DrawBatch();
11886 }
11887
11888 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11889 {
11890         int i;
11891         float f;
11892         float alpha;
11893         const float *v;
11894         const float *n;
11895         float *c;
11896         vec3_t ambientcolor;
11897         vec3_t diffusecolor;
11898         vec3_t lightdir;
11899         // TODO: optimize
11900         // model lighting
11901         VectorCopy(rsurface.modellight_lightdir, lightdir);
11902         f = 0.5f * r_refdef.lightmapintensity;
11903         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11904         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11905         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11906         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11907         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11908         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11909         alpha = *a;
11910         if (VectorLength2(diffusecolor) > 0)
11911         {
11912                 // q3-style directional shading
11913                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11914                 rsurface.passcolor4f_vertexbuffer = 0;
11915                 rsurface.passcolor4f_bufferoffset = 0;
11916                 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)
11917                 {
11918                         if ((f = DotProduct(n, lightdir)) > 0)
11919                                 VectorMA(ambientcolor, f, diffusecolor, c);
11920                         else
11921                                 VectorCopy(ambientcolor, c);
11922                         c[3] = alpha;
11923                 }
11924                 *r = 1;
11925                 *g = 1;
11926                 *b = 1;
11927                 *a = 1;
11928                 *applycolor = false;
11929         }
11930         else
11931         {
11932                 *r = ambientcolor[0];
11933                 *g = ambientcolor[1];
11934                 *b = ambientcolor[2];
11935                 rsurface.passcolor4f = NULL;
11936                 rsurface.passcolor4f_vertexbuffer = 0;
11937                 rsurface.passcolor4f_bufferoffset = 0;
11938         }
11939 }
11940
11941 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11942 {
11943         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
11944         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11945         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11946         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11947         GL_Color(r, g, b, a);
11948         RSurf_DrawBatch();
11949 }
11950
11951 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
11952 {
11953         int i;
11954         float f;
11955         const float *v;
11956         float *c;
11957         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
11958         {
11959                 f = 1 - RSurf_FogVertex(v);
11960                 c[0] = r;
11961                 c[1] = g;
11962                 c[2] = b;
11963                 c[3] = f * a;
11964         }
11965 }
11966
11967 void RSurf_SetupDepthAndCulling(void)
11968 {
11969         // submodels are biased to avoid z-fighting with world surfaces that they
11970         // may be exactly overlapping (avoids z-fighting artifacts on certain
11971         // doors and things in Quake maps)
11972         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11973         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11974         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11975         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11976 }
11977
11978 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11979 {
11980         // transparent sky would be ridiculous
11981         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11982                 return;
11983         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11984         skyrenderlater = true;
11985         RSurf_SetupDepthAndCulling();
11986         GL_DepthMask(true);
11987         // LordHavoc: HalfLife maps have freaky skypolys so don't use
11988         // skymasking on them, and Quake3 never did sky masking (unlike
11989         // software Quake and software Quake2), so disable the sky masking
11990         // in Quake3 maps as it causes problems with q3map2 sky tricks,
11991         // and skymasking also looks very bad when noclipping outside the
11992         // level, so don't use it then either.
11993         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
11994         {
11995                 R_Mesh_ResetTextureState();
11996                 if (skyrendermasked)
11997                 {
11998                         R_SetupShader_DepthOrShadow();
11999                         // depth-only (masking)
12000                         GL_ColorMask(0,0,0,0);
12001                         // just to make sure that braindead drivers don't draw
12002                         // anything despite that colormask...
12003                         GL_BlendFunc(GL_ZERO, GL_ONE);
12004                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12005                         if (rsurface.batchvertex3fbuffer)
12006                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12007                         else
12008                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12009                 }
12010                 else
12011                 {
12012                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12013                         // fog sky
12014                         GL_BlendFunc(GL_ONE, GL_ZERO);
12015                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12016                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12017                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12018                 }
12019                 RSurf_DrawBatch();
12020                 if (skyrendermasked)
12021                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12022         }
12023         R_Mesh_ResetTextureState();
12024         GL_Color(1, 1, 1, 1);
12025 }
12026
12027 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12028 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12029 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12030 {
12031         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12032                 return;
12033         if (prepass)
12034         {
12035                 // render screenspace normalmap to texture
12036                 GL_DepthMask(true);
12037                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12038                 RSurf_DrawBatch();
12039                 return;
12040         }
12041
12042         // bind lightmap texture
12043
12044         // water/refraction/reflection/camera surfaces have to be handled specially
12045         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12046         {
12047                 int start, end, startplaneindex;
12048                 for (start = 0;start < texturenumsurfaces;start = end)
12049                 {
12050                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12051                         if(startplaneindex < 0)
12052                         {
12053                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12054                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12055                                 end = start + 1;
12056                                 continue;
12057                         }
12058                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12059                                 ;
12060                         // now that we have a batch using the same planeindex, render it
12061                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12062                         {
12063                                 // render water or distortion background
12064                                 GL_DepthMask(true);
12065                                 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));
12066                                 RSurf_DrawBatch();
12067                                 // blend surface on top
12068                                 GL_DepthMask(false);
12069                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12070                                 RSurf_DrawBatch();
12071                         }
12072                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12073                         {
12074                                 // render surface with reflection texture as input
12075                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12076                                 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));
12077                                 RSurf_DrawBatch();
12078                         }
12079                 }
12080                 return;
12081         }
12082
12083         // render surface batch normally
12084         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12085         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12086         RSurf_DrawBatch();
12087 }
12088
12089 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12090 {
12091         // OpenGL 1.3 path - anything not completely ancient
12092         qboolean applycolor;
12093         qboolean applyfog;
12094         int layerindex;
12095         const texturelayer_t *layer;
12096         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);
12097         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12098
12099         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12100         {
12101                 vec4_t layercolor;
12102                 int layertexrgbscale;
12103                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12104                 {
12105                         if (layerindex == 0)
12106                                 GL_AlphaTest(true);
12107                         else
12108                         {
12109                                 GL_AlphaTest(false);
12110                                 GL_DepthFunc(GL_EQUAL);
12111                         }
12112                 }
12113                 GL_DepthMask(layer->depthmask && writedepth);
12114                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12115                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12116                 {
12117                         layertexrgbscale = 4;
12118                         VectorScale(layer->color, 0.25f, layercolor);
12119                 }
12120                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12121                 {
12122                         layertexrgbscale = 2;
12123                         VectorScale(layer->color, 0.5f, layercolor);
12124                 }
12125                 else
12126                 {
12127                         layertexrgbscale = 1;
12128                         VectorScale(layer->color, 1.0f, layercolor);
12129                 }
12130                 layercolor[3] = layer->color[3];
12131                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12132                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12133                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12134                 switch (layer->type)
12135                 {
12136                 case TEXTURELAYERTYPE_LITTEXTURE:
12137                         // single-pass lightmapped texture with 2x rgbscale
12138                         R_Mesh_TexBind(0, r_texture_white);
12139                         R_Mesh_TexMatrix(0, NULL);
12140                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12141                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12142                         R_Mesh_TexBind(1, layer->texture);
12143                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12144                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12145                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12146                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12147                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12148                         else if (FAKELIGHT_ENABLED)
12149                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12150                         else if (rsurface.uselightmaptexture)
12151                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12152                         else
12153                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12154                         break;
12155                 case TEXTURELAYERTYPE_TEXTURE:
12156                         // singletexture unlit texture with transparency support
12157                         R_Mesh_TexBind(0, layer->texture);
12158                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12159                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12160                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12161                         R_Mesh_TexBind(1, 0);
12162                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12163                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12164                         break;
12165                 case TEXTURELAYERTYPE_FOG:
12166                         // singletexture fogging
12167                         if (layer->texture)
12168                         {
12169                                 R_Mesh_TexBind(0, layer->texture);
12170                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12171                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12172                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12173                         }
12174                         else
12175                         {
12176                                 R_Mesh_TexBind(0, 0);
12177                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12178                         }
12179                         R_Mesh_TexBind(1, 0);
12180                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12181                         // generate a color array for the fog pass
12182                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12183                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12184                         RSurf_DrawBatch();
12185                         break;
12186                 default:
12187                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12188                 }
12189         }
12190         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12191         {
12192                 GL_DepthFunc(GL_LEQUAL);
12193                 GL_AlphaTest(false);
12194         }
12195 }
12196
12197 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12198 {
12199         // OpenGL 1.1 - crusty old voodoo path
12200         qboolean applyfog;
12201         int layerindex;
12202         const texturelayer_t *layer;
12203         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);
12204         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12205
12206         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12207         {
12208                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12209                 {
12210                         if (layerindex == 0)
12211                                 GL_AlphaTest(true);
12212                         else
12213                         {
12214                                 GL_AlphaTest(false);
12215                                 GL_DepthFunc(GL_EQUAL);
12216                         }
12217                 }
12218                 GL_DepthMask(layer->depthmask && writedepth);
12219                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12220                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12221                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12222                 switch (layer->type)
12223                 {
12224                 case TEXTURELAYERTYPE_LITTEXTURE:
12225                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12226                         {
12227                                 // two-pass lit texture with 2x rgbscale
12228                                 // first the lightmap pass
12229                                 R_Mesh_TexBind(0, r_texture_white);
12230                                 R_Mesh_TexMatrix(0, NULL);
12231                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12232                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12233                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12234                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12235                                 else if (FAKELIGHT_ENABLED)
12236                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12237                                 else if (rsurface.uselightmaptexture)
12238                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12239                                 else
12240                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12241                                 // then apply the texture to it
12242                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12243                                 R_Mesh_TexBind(0, layer->texture);
12244                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12245                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12246                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12247                                 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);
12248                         }
12249                         else
12250                         {
12251                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12252                                 R_Mesh_TexBind(0, layer->texture);
12253                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12254                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12255                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12256                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12257                                         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);
12258                                 else
12259                                         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);
12260                         }
12261                         break;
12262                 case TEXTURELAYERTYPE_TEXTURE:
12263                         // singletexture unlit texture with transparency support
12264                         R_Mesh_TexBind(0, layer->texture);
12265                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12266                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12267                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12268                         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);
12269                         break;
12270                 case TEXTURELAYERTYPE_FOG:
12271                         // singletexture fogging
12272                         if (layer->texture)
12273                         {
12274                                 R_Mesh_TexBind(0, layer->texture);
12275                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12276                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12277                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12278                         }
12279                         else
12280                         {
12281                                 R_Mesh_TexBind(0, 0);
12282                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12283                         }
12284                         // generate a color array for the fog pass
12285                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12286                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12287                         RSurf_DrawBatch();
12288                         break;
12289                 default:
12290                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12291                 }
12292         }
12293         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12294         {
12295                 GL_DepthFunc(GL_LEQUAL);
12296                 GL_AlphaTest(false);
12297         }
12298 }
12299
12300 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12301 {
12302         int vi;
12303         int j;
12304         r_vertexgeneric_t *batchvertex;
12305         float c[4];
12306
12307 //      R_Mesh_ResetTextureState();
12308         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12309
12310         if(rsurface.texture && rsurface.texture->currentskinframe)
12311         {
12312                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12313                 c[3] *= rsurface.texture->currentalpha;
12314         }
12315         else
12316         {
12317                 c[0] = 1;
12318                 c[1] = 0;
12319                 c[2] = 1;
12320                 c[3] = 1;
12321         }
12322
12323         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12324         {
12325                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12326                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12327                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12328         }
12329
12330         // brighten it up (as texture value 127 means "unlit")
12331         c[0] *= 2 * r_refdef.view.colorscale;
12332         c[1] *= 2 * r_refdef.view.colorscale;
12333         c[2] *= 2 * r_refdef.view.colorscale;
12334
12335         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12336                 c[3] *= r_wateralpha.value;
12337
12338         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12339         {
12340                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12341                 GL_DepthMask(false);
12342         }
12343         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12344         {
12345                 GL_BlendFunc(GL_ONE, GL_ONE);
12346                 GL_DepthMask(false);
12347         }
12348         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12349         {
12350                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12351                 GL_DepthMask(false);
12352         }
12353         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12354         {
12355                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12356                 GL_DepthMask(false);
12357         }
12358         else
12359         {
12360                 GL_BlendFunc(GL_ONE, GL_ZERO);
12361                 GL_DepthMask(writedepth);
12362         }
12363
12364         if (r_showsurfaces.integer == 3)
12365         {
12366                 rsurface.passcolor4f = NULL;
12367
12368                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12369                 {
12370                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12371
12372                         rsurface.passcolor4f = NULL;
12373                         rsurface.passcolor4f_vertexbuffer = 0;
12374                         rsurface.passcolor4f_bufferoffset = 0;
12375                 }
12376                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12377                 {
12378                         qboolean applycolor = true;
12379                         float one = 1.0;
12380
12381                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12382
12383                         r_refdef.lightmapintensity = 1;
12384                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12385                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12386                 }
12387                 else if (FAKELIGHT_ENABLED)
12388                 {
12389                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12390
12391                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12392                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12393                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12394                 }
12395                 else
12396                 {
12397                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12398
12399                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12400                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12401                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12402                 }
12403
12404                 if(!rsurface.passcolor4f)
12405                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12406
12407                 RSurf_DrawBatch_GL11_ApplyAmbient();
12408                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12409                 if(r_refdef.fogenabled)
12410                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12411                 RSurf_DrawBatch_GL11_ClampColor();
12412
12413                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12414                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12415                 RSurf_DrawBatch();
12416         }
12417         else if (!r_refdef.view.showdebug)
12418         {
12419                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12420                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12421                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12422                 {
12423                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12424                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
12425                 }
12426                 R_Mesh_PrepareVertices_Generic_Unlock();
12427                 RSurf_DrawBatch();
12428         }
12429         else if (r_showsurfaces.integer == 4)
12430         {
12431                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12432                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12433                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12434                 {
12435                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
12436                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12437                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
12438                 }
12439                 R_Mesh_PrepareVertices_Generic_Unlock();
12440                 RSurf_DrawBatch();
12441         }
12442         else if (r_showsurfaces.integer == 2)
12443         {
12444                 const int *e;
12445                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12446                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12447                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12448                 {
12449                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
12450                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12451                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12452                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12453                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
12454                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
12455                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
12456                 }
12457                 R_Mesh_PrepareVertices_Generic_Unlock();
12458                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12459         }
12460         else
12461         {
12462                 int texturesurfaceindex;
12463                 int k;
12464                 const msurface_t *surface;
12465                 float surfacecolor4f[4];
12466                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12467                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12468                 vi = 0;
12469                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12470                 {
12471                         surface = texturesurfacelist[texturesurfaceindex];
12472                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12473                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
12474                         for (j = 0;j < surface->num_vertices;j++)
12475                         {
12476                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12477                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
12478                                 vi++;
12479                         }
12480                 }
12481                 R_Mesh_PrepareVertices_Generic_Unlock();
12482                 RSurf_DrawBatch();
12483         }
12484 }
12485
12486 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12487 {
12488         CHECKGLERROR
12489         RSurf_SetupDepthAndCulling();
12490         if (r_showsurfaces.integer)
12491         {
12492                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12493                 return;
12494         }
12495         switch (vid.renderpath)
12496         {
12497         case RENDERPATH_GL20:
12498         case RENDERPATH_D3D9:
12499         case RENDERPATH_D3D10:
12500         case RENDERPATH_D3D11:
12501         case RENDERPATH_SOFT:
12502         case RENDERPATH_GLES2:
12503                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12504                 break;
12505         case RENDERPATH_GL13:
12506                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12507                 break;
12508         case RENDERPATH_GL11:
12509                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12510                 break;
12511         }
12512         CHECKGLERROR
12513 }
12514
12515 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12516 {
12517         CHECKGLERROR
12518         RSurf_SetupDepthAndCulling();
12519         if (r_showsurfaces.integer)
12520         {
12521                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12522                 return;
12523         }
12524         switch (vid.renderpath)
12525         {
12526         case RENDERPATH_GL20:
12527         case RENDERPATH_D3D9:
12528         case RENDERPATH_D3D10:
12529         case RENDERPATH_D3D11:
12530         case RENDERPATH_SOFT:
12531         case RENDERPATH_GLES2:
12532                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12533                 break;
12534         case RENDERPATH_GL13:
12535                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12536                 break;
12537         case RENDERPATH_GL11:
12538                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12539                 break;
12540         }
12541         CHECKGLERROR
12542 }
12543
12544 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12545 {
12546         int i, j;
12547         int texturenumsurfaces, endsurface;
12548         texture_t *texture;
12549         const msurface_t *surface;
12550 #define MAXBATCH_TRANSPARENTSURFACES 256
12551         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12552
12553         // if the model is static it doesn't matter what value we give for
12554         // wantnormals and wanttangents, so this logic uses only rules applicable
12555         // to a model, knowing that they are meaningless otherwise
12556         if (ent == r_refdef.scene.worldentity)
12557                 RSurf_ActiveWorldEntity();
12558         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12559                 RSurf_ActiveModelEntity(ent, false, false, false);
12560         else
12561         {
12562                 switch (vid.renderpath)
12563                 {
12564                 case RENDERPATH_GL20:
12565                 case RENDERPATH_D3D9:
12566                 case RENDERPATH_D3D10:
12567                 case RENDERPATH_D3D11:
12568                 case RENDERPATH_SOFT:
12569                 case RENDERPATH_GLES2:
12570                         RSurf_ActiveModelEntity(ent, true, true, false);
12571                         break;
12572                 case RENDERPATH_GL13:
12573                 case RENDERPATH_GL11:
12574                         RSurf_ActiveModelEntity(ent, true, false, false);
12575                         break;
12576                 }
12577         }
12578
12579         if (r_transparentdepthmasking.integer)
12580         {
12581                 qboolean setup = false;
12582                 for (i = 0;i < numsurfaces;i = j)
12583                 {
12584                         j = i + 1;
12585                         surface = rsurface.modelsurfaces + surfacelist[i];
12586                         texture = surface->texture;
12587                         rsurface.texture = R_GetCurrentTexture(texture);
12588                         rsurface.lightmaptexture = NULL;
12589                         rsurface.deluxemaptexture = NULL;
12590                         rsurface.uselightmaptexture = false;
12591                         // scan ahead until we find a different texture
12592                         endsurface = min(i + 1024, numsurfaces);
12593                         texturenumsurfaces = 0;
12594                         texturesurfacelist[texturenumsurfaces++] = surface;
12595                         for (;j < endsurface;j++)
12596                         {
12597                                 surface = rsurface.modelsurfaces + surfacelist[j];
12598                                 if (texture != surface->texture)
12599                                         break;
12600                                 texturesurfacelist[texturenumsurfaces++] = surface;
12601                         }
12602                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12603                                 continue;
12604                         // render the range of surfaces as depth
12605                         if (!setup)
12606                         {
12607                                 setup = true;
12608                                 GL_ColorMask(0,0,0,0);
12609                                 GL_Color(1,1,1,1);
12610                                 GL_DepthTest(true);
12611                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12612                                 GL_DepthMask(true);
12613 //                              R_Mesh_ResetTextureState();
12614                                 R_SetupShader_DepthOrShadow();
12615                         }
12616                         RSurf_SetupDepthAndCulling();
12617                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12618                         if (rsurface.batchvertex3fbuffer)
12619                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12620                         else
12621                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12622                         RSurf_DrawBatch();
12623                 }
12624                 if (setup)
12625                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12626         }
12627
12628         for (i = 0;i < numsurfaces;i = j)
12629         {
12630                 j = i + 1;
12631                 surface = rsurface.modelsurfaces + surfacelist[i];
12632                 texture = surface->texture;
12633                 rsurface.texture = R_GetCurrentTexture(texture);
12634                 // scan ahead until we find a different texture
12635                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12636                 texturenumsurfaces = 0;
12637                 texturesurfacelist[texturenumsurfaces++] = surface;
12638                 if(FAKELIGHT_ENABLED)
12639                 {
12640                         rsurface.lightmaptexture = NULL;
12641                         rsurface.deluxemaptexture = NULL;
12642                         rsurface.uselightmaptexture = false;
12643                         for (;j < endsurface;j++)
12644                         {
12645                                 surface = rsurface.modelsurfaces + surfacelist[j];
12646                                 if (texture != surface->texture)
12647                                         break;
12648                                 texturesurfacelist[texturenumsurfaces++] = surface;
12649                         }
12650                 }
12651                 else
12652                 {
12653                         rsurface.lightmaptexture = surface->lightmaptexture;
12654                         rsurface.deluxemaptexture = surface->deluxemaptexture;
12655                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12656                         for (;j < endsurface;j++)
12657                         {
12658                                 surface = rsurface.modelsurfaces + surfacelist[j];
12659                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12660                                         break;
12661                                 texturesurfacelist[texturenumsurfaces++] = surface;
12662                         }
12663                 }
12664                 // render the range of surfaces
12665                 if (ent == r_refdef.scene.worldentity)
12666                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12667                 else
12668                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12669         }
12670         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12671 }
12672
12673 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12674 {
12675         // transparent surfaces get pushed off into the transparent queue
12676         int surfacelistindex;
12677         const msurface_t *surface;
12678         vec3_t tempcenter, center;
12679         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12680         {
12681                 surface = texturesurfacelist[surfacelistindex];
12682                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12683                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12684                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12685                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12686                 if (queueentity->transparent_offset) // transparent offset
12687                 {
12688                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12689                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12690                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12691                 }
12692                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12693         }
12694 }
12695
12696 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12697 {
12698         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12699                 return;
12700         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12701                 return;
12702         RSurf_SetupDepthAndCulling();
12703         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12704         if (rsurface.batchvertex3fbuffer)
12705                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12706         else
12707                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12708         RSurf_DrawBatch();
12709 }
12710
12711 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12712 {
12713         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12714         CHECKGLERROR
12715         if (depthonly)
12716                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12717         else if (prepass)
12718         {
12719                 if (!rsurface.texture->currentnumlayers)
12720                         return;
12721                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12722                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12723                 else
12724                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12725         }
12726         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12727                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12728         else if (!rsurface.texture->currentnumlayers)
12729                 return;
12730         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12731         {
12732                 // in the deferred case, transparent surfaces were queued during prepass
12733                 if (!r_shadow_usingdeferredprepass)
12734                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12735         }
12736         else
12737         {
12738                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12739                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12740         }
12741         CHECKGLERROR
12742 }
12743
12744 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12745 {
12746         int i, j;
12747         texture_t *texture;
12748         R_FrameData_SetMark();
12749         // break the surface list down into batches by texture and use of lightmapping
12750         for (i = 0;i < numsurfaces;i = j)
12751         {
12752                 j = i + 1;
12753                 // texture is the base texture pointer, rsurface.texture is the
12754                 // current frame/skin the texture is directing us to use (for example
12755                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12756                 // use skin 1 instead)
12757                 texture = surfacelist[i]->texture;
12758                 rsurface.texture = R_GetCurrentTexture(texture);
12759                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12760                 {
12761                         // if this texture is not the kind we want, skip ahead to the next one
12762                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12763                                 ;
12764                         continue;
12765                 }
12766                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12767                 {
12768                         rsurface.lightmaptexture = NULL;
12769                         rsurface.deluxemaptexture = NULL;
12770                         rsurface.uselightmaptexture = false;
12771                         // simply scan ahead until we find a different texture or lightmap state
12772                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12773                                 ;
12774                 }
12775                 else
12776                 {
12777                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12778                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12779                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12780                         // simply scan ahead until we find a different texture or lightmap state
12781                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12782                                 ;
12783                 }
12784                 // render the range of surfaces
12785                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12786         }
12787         R_FrameData_ReturnToMark();
12788 }
12789
12790 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12791 {
12792         CHECKGLERROR
12793         if (depthonly)
12794                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12795         else if (prepass)
12796         {
12797                 if (!rsurface.texture->currentnumlayers)
12798                         return;
12799                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12800                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12801                 else
12802                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12803         }
12804         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12805                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12806         else if (!rsurface.texture->currentnumlayers)
12807                 return;
12808         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12809         {
12810                 // in the deferred case, transparent surfaces were queued during prepass
12811                 if (!r_shadow_usingdeferredprepass)
12812                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12813         }
12814         else
12815         {
12816                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12817                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12818         }
12819         CHECKGLERROR
12820 }
12821
12822 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12823 {
12824         int i, j;
12825         texture_t *texture;
12826         R_FrameData_SetMark();
12827         // break the surface list down into batches by texture and use of lightmapping
12828         for (i = 0;i < numsurfaces;i = j)
12829         {
12830                 j = i + 1;
12831                 // texture is the base texture pointer, rsurface.texture is the
12832                 // current frame/skin the texture is directing us to use (for example
12833                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12834                 // use skin 1 instead)
12835                 texture = surfacelist[i]->texture;
12836                 rsurface.texture = R_GetCurrentTexture(texture);
12837                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12838                 {
12839                         // if this texture is not the kind we want, skip ahead to the next one
12840                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12841                                 ;
12842                         continue;
12843                 }
12844                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12845                 {
12846                         rsurface.lightmaptexture = NULL;
12847                         rsurface.deluxemaptexture = NULL;
12848                         rsurface.uselightmaptexture = false;
12849                         // simply scan ahead until we find a different texture or lightmap state
12850                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12851                                 ;
12852                 }
12853                 else
12854                 {
12855                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12856                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12857                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12858                         // simply scan ahead until we find a different texture or lightmap state
12859                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12860                                 ;
12861                 }
12862                 // render the range of surfaces
12863                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12864         }
12865         R_FrameData_ReturnToMark();
12866 }
12867
12868 float locboxvertex3f[6*4*3] =
12869 {
12870         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12871         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12872         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12873         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12874         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12875         1,0,0, 0,0,0, 0,1,0, 1,1,0
12876 };
12877
12878 unsigned short locboxelements[6*2*3] =
12879 {
12880          0, 1, 2, 0, 2, 3,
12881          4, 5, 6, 4, 6, 7,
12882          8, 9,10, 8,10,11,
12883         12,13,14, 12,14,15,
12884         16,17,18, 16,18,19,
12885         20,21,22, 20,22,23
12886 };
12887
12888 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12889 {
12890         int i, j;
12891         cl_locnode_t *loc = (cl_locnode_t *)ent;
12892         vec3_t mins, size;
12893         float vertex3f[6*4*3];
12894         CHECKGLERROR
12895         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12896         GL_DepthMask(false);
12897         GL_DepthRange(0, 1);
12898         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12899         GL_DepthTest(true);
12900         GL_CullFace(GL_NONE);
12901         R_EntityMatrix(&identitymatrix);
12902
12903 //      R_Mesh_ResetTextureState();
12904
12905         i = surfacelist[0];
12906         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12907                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12908                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12909                         surfacelist[0] < 0 ? 0.5f : 0.125f);
12910
12911         if (VectorCompare(loc->mins, loc->maxs))
12912         {
12913                 VectorSet(size, 2, 2, 2);
12914                 VectorMA(loc->mins, -0.5f, size, mins);
12915         }
12916         else
12917         {
12918                 VectorCopy(loc->mins, mins);
12919                 VectorSubtract(loc->maxs, loc->mins, size);
12920         }
12921
12922         for (i = 0;i < 6*4*3;)
12923                 for (j = 0;j < 3;j++, i++)
12924                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12925
12926         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12927         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12928         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12929 }
12930
12931 void R_DrawLocs(void)
12932 {
12933         int index;
12934         cl_locnode_t *loc, *nearestloc;
12935         vec3_t center;
12936         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12937         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12938         {
12939                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12940                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12941         }
12942 }
12943
12944 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12945 {
12946         if (decalsystem->decals)
12947                 Mem_Free(decalsystem->decals);
12948         memset(decalsystem, 0, sizeof(*decalsystem));
12949 }
12950
12951 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)
12952 {
12953         tridecal_t *decal;
12954         tridecal_t *decals;
12955         int i;
12956
12957         // expand or initialize the system
12958         if (decalsystem->maxdecals <= decalsystem->numdecals)
12959         {
12960                 decalsystem_t old = *decalsystem;
12961                 qboolean useshortelements;
12962                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12963                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12964                 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)));
12965                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12966                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12967                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12968                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12969                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12970                 if (decalsystem->numdecals)
12971                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12972                 if (old.decals)
12973                         Mem_Free(old.decals);
12974                 for (i = 0;i < decalsystem->maxdecals*3;i++)
12975                         decalsystem->element3i[i] = i;
12976                 if (useshortelements)
12977                         for (i = 0;i < decalsystem->maxdecals*3;i++)
12978                                 decalsystem->element3s[i] = i;
12979         }
12980
12981         // grab a decal and search for another free slot for the next one
12982         decals = decalsystem->decals;
12983         decal = decalsystem->decals + (i = decalsystem->freedecal++);
12984         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
12985                 ;
12986         decalsystem->freedecal = i;
12987         if (decalsystem->numdecals <= i)
12988                 decalsystem->numdecals = i + 1;
12989
12990         // initialize the decal
12991         decal->lived = 0;
12992         decal->triangleindex = triangleindex;
12993         decal->surfaceindex = surfaceindex;
12994         decal->decalsequence = decalsequence;
12995         decal->color4f[0][0] = c0[0];
12996         decal->color4f[0][1] = c0[1];
12997         decal->color4f[0][2] = c0[2];
12998         decal->color4f[0][3] = 1;
12999         decal->color4f[1][0] = c1[0];
13000         decal->color4f[1][1] = c1[1];
13001         decal->color4f[1][2] = c1[2];
13002         decal->color4f[1][3] = 1;
13003         decal->color4f[2][0] = c2[0];
13004         decal->color4f[2][1] = c2[1];
13005         decal->color4f[2][2] = c2[2];
13006         decal->color4f[2][3] = 1;
13007         decal->vertex3f[0][0] = v0[0];
13008         decal->vertex3f[0][1] = v0[1];
13009         decal->vertex3f[0][2] = v0[2];
13010         decal->vertex3f[1][0] = v1[0];
13011         decal->vertex3f[1][1] = v1[1];
13012         decal->vertex3f[1][2] = v1[2];
13013         decal->vertex3f[2][0] = v2[0];
13014         decal->vertex3f[2][1] = v2[1];
13015         decal->vertex3f[2][2] = v2[2];
13016         decal->texcoord2f[0][0] = t0[0];
13017         decal->texcoord2f[0][1] = t0[1];
13018         decal->texcoord2f[1][0] = t1[0];
13019         decal->texcoord2f[1][1] = t1[1];
13020         decal->texcoord2f[2][0] = t2[0];
13021         decal->texcoord2f[2][1] = t2[1];
13022 }
13023
13024 extern cvar_t cl_decals_bias;
13025 extern cvar_t cl_decals_models;
13026 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13027 // baseparms, parms, temps
13028 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)
13029 {
13030         int cornerindex;
13031         int index;
13032         float v[9][3];
13033         const float *vertex3f;
13034         const float *normal3f;
13035         int numpoints;
13036         float points[2][9][3];
13037         float temp[3];
13038         float tc[9][2];
13039         float f;
13040         float c[9][4];
13041         const int *e;
13042
13043         e = rsurface.modelelement3i + 3*triangleindex;
13044
13045         vertex3f = rsurface.modelvertex3f;
13046         normal3f = rsurface.modelnormal3f;
13047
13048         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13049         {
13050                 index = 3*e[cornerindex];
13051                 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
13052         }
13053         // cull backfaces
13054         //TriangleNormal(v[0], v[1], v[2], normal);
13055         //if (DotProduct(normal, localnormal) < 0.0f)
13056         //      continue;
13057         // clip by each of the box planes formed from the projection matrix
13058         // if anything survives, we emit the decal
13059         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]);
13060         if (numpoints < 3)
13061                 return;
13062         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]);
13063         if (numpoints < 3)
13064                 return;
13065         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]);
13066         if (numpoints < 3)
13067                 return;
13068         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]);
13069         if (numpoints < 3)
13070                 return;
13071         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]);
13072         if (numpoints < 3)
13073                 return;
13074         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]);
13075         if (numpoints < 3)
13076                 return;
13077         // some part of the triangle survived, so we have to accept it...
13078         if (dynamic)
13079         {
13080                 // dynamic always uses the original triangle
13081                 numpoints = 3;
13082                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13083                 {
13084                         index = 3*e[cornerindex];
13085                         VectorCopy(vertex3f + index, v[cornerindex]);
13086                 }
13087         }
13088         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13089         {
13090                 // convert vertex positions to texcoords
13091                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13092                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13093                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13094                 // calculate distance fade from the projection origin
13095                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13096                 f = bound(0.0f, f, 1.0f);
13097                 c[cornerindex][0] = r * f;
13098                 c[cornerindex][1] = g * f;
13099                 c[cornerindex][2] = b * f;
13100                 c[cornerindex][3] = 1.0f;
13101                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13102         }
13103         if (dynamic)
13104                 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);
13105         else
13106                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13107                         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);
13108 }
13109 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)
13110 {
13111         matrix4x4_t projection;
13112         decalsystem_t *decalsystem;
13113         qboolean dynamic;
13114         dp_model_t *model;
13115         const msurface_t *surface;
13116         const msurface_t *surfaces;
13117         const int *surfacelist;
13118         const texture_t *texture;
13119         int numtriangles;
13120         int numsurfacelist;
13121         int surfacelistindex;
13122         int surfaceindex;
13123         int triangleindex;
13124         float localorigin[3];
13125         float localnormal[3];
13126         float localmins[3];
13127         float localmaxs[3];
13128         float localsize;
13129         //float normal[3];
13130         float planes[6][4];
13131         float angles[3];
13132         bih_t *bih;
13133         int bih_triangles_count;
13134         int bih_triangles[256];
13135         int bih_surfaces[256];
13136
13137         decalsystem = &ent->decalsystem;
13138         model = ent->model;
13139         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13140         {
13141                 R_DecalSystem_Reset(&ent->decalsystem);
13142                 return;
13143         }
13144
13145         if (!model->brush.data_leafs && !cl_decals_models.integer)
13146         {
13147                 if (decalsystem->model)
13148                         R_DecalSystem_Reset(decalsystem);
13149                 return;
13150         }
13151
13152         if (decalsystem->model != model)
13153                 R_DecalSystem_Reset(decalsystem);
13154         decalsystem->model = model;
13155
13156         RSurf_ActiveModelEntity(ent, true, false, false);
13157
13158         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13159         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13160         VectorNormalize(localnormal);
13161         localsize = worldsize*rsurface.inversematrixscale;
13162         localmins[0] = localorigin[0] - localsize;
13163         localmins[1] = localorigin[1] - localsize;
13164         localmins[2] = localorigin[2] - localsize;
13165         localmaxs[0] = localorigin[0] + localsize;
13166         localmaxs[1] = localorigin[1] + localsize;
13167         localmaxs[2] = localorigin[2] + localsize;
13168
13169         //VectorCopy(localnormal, planes[4]);
13170         //VectorVectors(planes[4], planes[2], planes[0]);
13171         AnglesFromVectors(angles, localnormal, NULL, false);
13172         AngleVectors(angles, planes[0], planes[2], planes[4]);
13173         VectorNegate(planes[0], planes[1]);
13174         VectorNegate(planes[2], planes[3]);
13175         VectorNegate(planes[4], planes[5]);
13176         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13177         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13178         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13179         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13180         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13181         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13182
13183 #if 1
13184 // works
13185 {
13186         matrix4x4_t forwardprojection;
13187         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13188         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13189 }
13190 #else
13191 // broken
13192 {
13193         float projectionvector[4][3];
13194         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13195         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13196         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13197         projectionvector[0][0] = planes[0][0] * ilocalsize;
13198         projectionvector[0][1] = planes[1][0] * ilocalsize;
13199         projectionvector[0][2] = planes[2][0] * ilocalsize;
13200         projectionvector[1][0] = planes[0][1] * ilocalsize;
13201         projectionvector[1][1] = planes[1][1] * ilocalsize;
13202         projectionvector[1][2] = planes[2][1] * ilocalsize;
13203         projectionvector[2][0] = planes[0][2] * ilocalsize;
13204         projectionvector[2][1] = planes[1][2] * ilocalsize;
13205         projectionvector[2][2] = planes[2][2] * ilocalsize;
13206         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13207         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13208         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13209         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13210 }
13211 #endif
13212
13213         dynamic = model->surfmesh.isanimated;
13214         numsurfacelist = model->nummodelsurfaces;
13215         surfacelist = model->sortedmodelsurfaces;
13216         surfaces = model->data_surfaces;
13217
13218         bih = NULL;
13219         bih_triangles_count = -1;
13220         if(!dynamic)
13221         {
13222                 if(model->render_bih.numleafs)
13223                         bih = &model->render_bih;
13224                 else if(model->collision_bih.numleafs)
13225                         bih = &model->collision_bih;
13226         }
13227         if(bih)
13228                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13229         if(bih_triangles_count == 0)
13230                 return;
13231         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13232                 return;
13233         if(bih_triangles_count > 0)
13234         {
13235                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13236                 {
13237                         surfaceindex = bih_surfaces[triangleindex];
13238                         surface = surfaces + surfaceindex;
13239                         texture = surface->texture;
13240                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13241                                 continue;
13242                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13243                                 continue;
13244                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13245                 }
13246         }
13247         else
13248         {
13249                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13250                 {
13251                         surfaceindex = surfacelist[surfacelistindex];
13252                         surface = surfaces + surfaceindex;
13253                         // check cull box first because it rejects more than any other check
13254                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13255                                 continue;
13256                         // skip transparent surfaces
13257                         texture = surface->texture;
13258                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13259                                 continue;
13260                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13261                                 continue;
13262                         numtriangles = surface->num_triangles;
13263                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13264                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13265                 }
13266         }
13267 }
13268
13269 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13270 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)
13271 {
13272         int renderentityindex;
13273         float worldmins[3];
13274         float worldmaxs[3];
13275         entity_render_t *ent;
13276
13277         if (!cl_decals_newsystem.integer)
13278                 return;
13279
13280         worldmins[0] = worldorigin[0] - worldsize;
13281         worldmins[1] = worldorigin[1] - worldsize;
13282         worldmins[2] = worldorigin[2] - worldsize;
13283         worldmaxs[0] = worldorigin[0] + worldsize;
13284         worldmaxs[1] = worldorigin[1] + worldsize;
13285         worldmaxs[2] = worldorigin[2] + worldsize;
13286
13287         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13288
13289         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13290         {
13291                 ent = r_refdef.scene.entities[renderentityindex];
13292                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13293                         continue;
13294
13295                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13296         }
13297 }
13298
13299 typedef struct r_decalsystem_splatqueue_s
13300 {
13301         vec3_t worldorigin;
13302         vec3_t worldnormal;
13303         float color[4];
13304         float tcrange[4];
13305         float worldsize;
13306         int decalsequence;
13307 }
13308 r_decalsystem_splatqueue_t;
13309
13310 int r_decalsystem_numqueued = 0;
13311 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13312
13313 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)
13314 {
13315         r_decalsystem_splatqueue_t *queue;
13316
13317         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13318                 return;
13319
13320         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13321         VectorCopy(worldorigin, queue->worldorigin);
13322         VectorCopy(worldnormal, queue->worldnormal);
13323         Vector4Set(queue->color, r, g, b, a);
13324         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13325         queue->worldsize = worldsize;
13326         queue->decalsequence = cl.decalsequence++;
13327 }
13328
13329 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13330 {
13331         int i;
13332         r_decalsystem_splatqueue_t *queue;
13333
13334         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13335                 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);
13336         r_decalsystem_numqueued = 0;
13337 }
13338
13339 extern cvar_t cl_decals_max;
13340 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13341 {
13342         int i;
13343         decalsystem_t *decalsystem = &ent->decalsystem;
13344         int numdecals;
13345         int killsequence;
13346         tridecal_t *decal;
13347         float frametime;
13348         float lifetime;
13349
13350         if (!decalsystem->numdecals)
13351                 return;
13352
13353         if (r_showsurfaces.integer)
13354                 return;
13355
13356         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13357         {
13358                 R_DecalSystem_Reset(decalsystem);
13359                 return;
13360         }
13361
13362         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13363         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13364
13365         if (decalsystem->lastupdatetime)
13366                 frametime = (cl.time - decalsystem->lastupdatetime);
13367         else
13368                 frametime = 0;
13369         decalsystem->lastupdatetime = cl.time;
13370         decal = decalsystem->decals;
13371         numdecals = decalsystem->numdecals;
13372
13373         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13374         {
13375                 if (decal->color4f[0][3])
13376                 {
13377                         decal->lived += frametime;
13378                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13379                         {
13380                                 memset(decal, 0, sizeof(*decal));
13381                                 if (decalsystem->freedecal > i)
13382                                         decalsystem->freedecal = i;
13383                         }
13384                 }
13385         }
13386         decal = decalsystem->decals;
13387         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
13388                 numdecals--;
13389
13390         // collapse the array by shuffling the tail decals into the gaps
13391         for (;;)
13392         {
13393                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
13394                         decalsystem->freedecal++;
13395                 if (decalsystem->freedecal == numdecals)
13396                         break;
13397                 decal[decalsystem->freedecal] = decal[--numdecals];
13398         }
13399
13400         decalsystem->numdecals = numdecals;
13401
13402         if (numdecals <= 0)
13403         {
13404                 // if there are no decals left, reset decalsystem
13405                 R_DecalSystem_Reset(decalsystem);
13406         }
13407 }
13408
13409 extern skinframe_t *decalskinframe;
13410 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13411 {
13412         int i;
13413         decalsystem_t *decalsystem = &ent->decalsystem;
13414         int numdecals;
13415         tridecal_t *decal;
13416         float faderate;
13417         float alpha;
13418         float *v3f;
13419         float *c4f;
13420         float *t2f;
13421         const int *e;
13422         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13423         int numtris = 0;
13424
13425         numdecals = decalsystem->numdecals;
13426         if (!numdecals)
13427                 return;
13428
13429         if (r_showsurfaces.integer)
13430                 return;
13431
13432         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13433         {
13434                 R_DecalSystem_Reset(decalsystem);
13435                 return;
13436         }
13437
13438         // if the model is static it doesn't matter what value we give for
13439         // wantnormals and wanttangents, so this logic uses only rules applicable
13440         // to a model, knowing that they are meaningless otherwise
13441         if (ent == r_refdef.scene.worldentity)
13442                 RSurf_ActiveWorldEntity();
13443         else
13444                 RSurf_ActiveModelEntity(ent, false, false, false);
13445
13446         decalsystem->lastupdatetime = cl.time;
13447         decal = decalsystem->decals;
13448
13449         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13450
13451         // update vertex positions for animated models
13452         v3f = decalsystem->vertex3f;
13453         c4f = decalsystem->color4f;
13454         t2f = decalsystem->texcoord2f;
13455         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13456         {
13457                 if (!decal->color4f[0][3])
13458                         continue;
13459
13460                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13461                         continue;
13462
13463                 // update color values for fading decals
13464                 if (decal->lived >= cl_decals_time.value)
13465                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13466                 else
13467                         alpha = 1.0f;
13468
13469                 c4f[ 0] = decal->color4f[0][0] * alpha;
13470                 c4f[ 1] = decal->color4f[0][1] * alpha;
13471                 c4f[ 2] = decal->color4f[0][2] * alpha;
13472                 c4f[ 3] = 1;
13473                 c4f[ 4] = decal->color4f[1][0] * alpha;
13474                 c4f[ 5] = decal->color4f[1][1] * alpha;
13475                 c4f[ 6] = decal->color4f[1][2] * alpha;
13476                 c4f[ 7] = 1;
13477                 c4f[ 8] = decal->color4f[2][0] * alpha;
13478                 c4f[ 9] = decal->color4f[2][1] * alpha;
13479                 c4f[10] = decal->color4f[2][2] * alpha;
13480                 c4f[11] = 1;
13481
13482                 t2f[0] = decal->texcoord2f[0][0];
13483                 t2f[1] = decal->texcoord2f[0][1];
13484                 t2f[2] = decal->texcoord2f[1][0];
13485                 t2f[3] = decal->texcoord2f[1][1];
13486                 t2f[4] = decal->texcoord2f[2][0];
13487                 t2f[5] = decal->texcoord2f[2][1];
13488
13489                 // update vertex positions for animated models
13490                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13491                 {
13492                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13493                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
13494                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
13495                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
13496                 }
13497                 else
13498                 {
13499                         VectorCopy(decal->vertex3f[0], v3f);
13500                         VectorCopy(decal->vertex3f[1], v3f + 3);
13501                         VectorCopy(decal->vertex3f[2], v3f + 6);
13502                 }
13503
13504                 if (r_refdef.fogenabled)
13505                 {
13506                         alpha = RSurf_FogVertex(v3f);
13507                         VectorScale(c4f, alpha, c4f);
13508                         alpha = RSurf_FogVertex(v3f + 3);
13509                         VectorScale(c4f + 4, alpha, c4f + 4);
13510                         alpha = RSurf_FogVertex(v3f + 6);
13511                         VectorScale(c4f + 8, alpha, c4f + 8);
13512                 }
13513
13514                 v3f += 9;
13515                 c4f += 12;
13516                 t2f += 6;
13517                 numtris++;
13518         }
13519
13520         if (numtris > 0)
13521         {
13522                 r_refdef.stats.drawndecals += numtris;
13523
13524                 // now render the decals all at once
13525                 // (this assumes they all use one particle font texture!)
13526                 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);
13527 //              R_Mesh_ResetTextureState();
13528                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13529                 GL_DepthMask(false);
13530                 GL_DepthRange(0, 1);
13531                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13532                 GL_DepthTest(true);
13533                 GL_CullFace(GL_NONE);
13534                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13535                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13536                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13537         }
13538 }
13539
13540 static void R_DrawModelDecals(void)
13541 {
13542         int i, numdecals;
13543
13544         // fade faster when there are too many decals
13545         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13546         for (i = 0;i < r_refdef.scene.numentities;i++)
13547                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13548
13549         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13550         for (i = 0;i < r_refdef.scene.numentities;i++)
13551                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13552                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13553
13554         R_DecalSystem_ApplySplatEntitiesQueue();
13555
13556         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13557         for (i = 0;i < r_refdef.scene.numentities;i++)
13558                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13559
13560         r_refdef.stats.totaldecals += numdecals;
13561
13562         if (r_showsurfaces.integer)
13563                 return;
13564
13565         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13566
13567         for (i = 0;i < r_refdef.scene.numentities;i++)
13568         {
13569                 if (!r_refdef.viewcache.entityvisible[i])
13570                         continue;
13571                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13572                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13573         }
13574 }
13575
13576 extern cvar_t mod_collision_bih;
13577 void R_DrawDebugModel(void)
13578 {
13579         entity_render_t *ent = rsurface.entity;
13580         int i, j, k, l, flagsmask;
13581         const msurface_t *surface;
13582         dp_model_t *model = ent->model;
13583         vec3_t v;
13584
13585         switch(vid.renderpath)
13586         {
13587         case RENDERPATH_GL11:
13588         case RENDERPATH_GL13:
13589         case RENDERPATH_GL20:
13590                 break;
13591         case RENDERPATH_D3D9:
13592                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13593                 return;
13594         case RENDERPATH_D3D10:
13595                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13596                 return;
13597         case RENDERPATH_D3D11:
13598                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13599                 return;
13600         case RENDERPATH_SOFT:
13601                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13602                 return;
13603         case RENDERPATH_GLES2:
13604                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13605                 return;
13606         }
13607
13608         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13609
13610 //      R_Mesh_ResetTextureState();
13611         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13612         GL_DepthRange(0, 1);
13613         GL_DepthTest(!r_showdisabledepthtest.integer);
13614         GL_DepthMask(false);
13615         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13616
13617         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13618         {
13619                 int triangleindex;
13620                 int bihleafindex;
13621                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13622                 const q3mbrush_t *brush;
13623                 const bih_t *bih = &model->collision_bih;
13624                 const bih_leaf_t *bihleaf;
13625                 float vertex3f[3][3];
13626                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13627                 cullbox = false;
13628                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13629                 {
13630                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13631                                 continue;
13632                         switch (bihleaf->type)
13633                         {
13634                         case BIH_BRUSH:
13635                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13636                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13637                                 {
13638                                         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);
13639                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13640                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13641                                 }
13642                                 break;
13643                         case BIH_COLLISIONTRIANGLE:
13644                                 triangleindex = bihleaf->itemindex;
13645                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13646                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13647                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13648                                 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);
13649                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13650                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13651                                 break;
13652                         case BIH_RENDERTRIANGLE:
13653                                 triangleindex = bihleaf->itemindex;
13654                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13655                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13656                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13657                                 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);
13658                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13659                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13660                                 break;
13661                         }
13662                 }
13663         }
13664
13665         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13666
13667         if (r_showtris.integer || (r_shownormals.value != 0))
13668         {
13669                 if (r_showdisabledepthtest.integer)
13670                 {
13671                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13672                         GL_DepthMask(false);
13673                 }
13674                 else
13675                 {
13676                         GL_BlendFunc(GL_ONE, GL_ZERO);
13677                         GL_DepthMask(true);
13678                 }
13679                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13680                 {
13681                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13682                                 continue;
13683                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13684                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13685                         {
13686                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13687                                 if (r_showtris.value > 0)
13688                                 {
13689                                         if (!rsurface.texture->currentlayers->depthmask)
13690                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13691                                         else if (ent == r_refdef.scene.worldentity)
13692                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13693                                         else
13694                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13695                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13696                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13697                                         RSurf_DrawBatch();
13698                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13699                                         CHECKGLERROR
13700                                 }
13701                                 if (r_shownormals.value < 0)
13702                                 {
13703                                         qglBegin(GL_LINES);
13704                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13705                                         {
13706                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13707                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13708                                                 qglVertex3f(v[0], v[1], v[2]);
13709                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13710                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13711                                                 qglVertex3f(v[0], v[1], v[2]);
13712                                         }
13713                                         qglEnd();
13714                                         CHECKGLERROR
13715                                 }
13716                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13717                                 {
13718                                         qglBegin(GL_LINES);
13719                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13720                                         {
13721                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13722                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13723                                                 qglVertex3f(v[0], v[1], v[2]);
13724                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13725                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13726                                                 qglVertex3f(v[0], v[1], v[2]);
13727                                         }
13728                                         qglEnd();
13729                                         CHECKGLERROR
13730                                         qglBegin(GL_LINES);
13731                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13732                                         {
13733                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13734                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13735                                                 qglVertex3f(v[0], v[1], v[2]);
13736                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13737                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13738                                                 qglVertex3f(v[0], v[1], v[2]);
13739                                         }
13740                                         qglEnd();
13741                                         CHECKGLERROR
13742                                         qglBegin(GL_LINES);
13743                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13744                                         {
13745                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13746                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13747                                                 qglVertex3f(v[0], v[1], v[2]);
13748                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13749                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13750                                                 qglVertex3f(v[0], v[1], v[2]);
13751                                         }
13752                                         qglEnd();
13753                                         CHECKGLERROR
13754                                 }
13755                         }
13756                 }
13757                 rsurface.texture = NULL;
13758         }
13759 }
13760
13761 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13762 int r_maxsurfacelist = 0;
13763 const msurface_t **r_surfacelist = NULL;
13764 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13765 {
13766         int i, j, endj, flagsmask;
13767         dp_model_t *model = r_refdef.scene.worldmodel;
13768         msurface_t *surfaces;
13769         unsigned char *update;
13770         int numsurfacelist = 0;
13771         if (model == NULL)
13772                 return;
13773
13774         if (r_maxsurfacelist < model->num_surfaces)
13775         {
13776                 r_maxsurfacelist = model->num_surfaces;
13777                 if (r_surfacelist)
13778                         Mem_Free((msurface_t**)r_surfacelist);
13779                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13780         }
13781
13782         RSurf_ActiveWorldEntity();
13783
13784         surfaces = model->data_surfaces;
13785         update = model->brushq1.lightmapupdateflags;
13786
13787         // update light styles on this submodel
13788         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13789         {
13790                 model_brush_lightstyleinfo_t *style;
13791                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13792                 {
13793                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13794                         {
13795                                 int *list = style->surfacelist;
13796                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13797                                 for (j = 0;j < style->numsurfaces;j++)
13798                                         update[list[j]] = true;
13799                         }
13800                 }
13801         }
13802
13803         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13804
13805         if (debug)
13806         {
13807                 R_DrawDebugModel();
13808                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13809                 return;
13810         }
13811
13812         rsurface.lightmaptexture = NULL;
13813         rsurface.deluxemaptexture = NULL;
13814         rsurface.uselightmaptexture = false;
13815         rsurface.texture = NULL;
13816         rsurface.rtlight = NULL;
13817         numsurfacelist = 0;
13818         // add visible surfaces to draw list
13819         for (i = 0;i < model->nummodelsurfaces;i++)
13820         {
13821                 j = model->sortedmodelsurfaces[i];
13822                 if (r_refdef.viewcache.world_surfacevisible[j])
13823                         r_surfacelist[numsurfacelist++] = surfaces + j;
13824         }
13825         // update lightmaps if needed
13826         if (model->brushq1.firstrender)
13827         {
13828                 model->brushq1.firstrender = false;
13829                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13830                         if (update[j])
13831                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13832         }
13833         else if (update)
13834         {
13835                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13836                         if (r_refdef.viewcache.world_surfacevisible[j])
13837                                 if (update[j])
13838                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13839         }
13840         // don't do anything if there were no surfaces
13841         if (!numsurfacelist)
13842         {
13843                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13844                 return;
13845         }
13846         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13847
13848         // add to stats if desired
13849         if (r_speeds.integer && !skysurfaces && !depthonly)
13850         {
13851                 r_refdef.stats.world_surfaces += numsurfacelist;
13852                 for (j = 0;j < numsurfacelist;j++)
13853                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13854         }
13855
13856         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13857 }
13858
13859 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13860 {
13861         int i, j, endj, flagsmask;
13862         dp_model_t *model = ent->model;
13863         msurface_t *surfaces;
13864         unsigned char *update;
13865         int numsurfacelist = 0;
13866         if (model == NULL)
13867                 return;
13868
13869         if (r_maxsurfacelist < model->num_surfaces)
13870         {
13871                 r_maxsurfacelist = model->num_surfaces;
13872                 if (r_surfacelist)
13873                         Mem_Free((msurface_t **)r_surfacelist);
13874                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13875         }
13876
13877         // if the model is static it doesn't matter what value we give for
13878         // wantnormals and wanttangents, so this logic uses only rules applicable
13879         // to a model, knowing that they are meaningless otherwise
13880         if (ent == r_refdef.scene.worldentity)
13881                 RSurf_ActiveWorldEntity();
13882         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13883                 RSurf_ActiveModelEntity(ent, false, false, false);
13884         else if (prepass)
13885                 RSurf_ActiveModelEntity(ent, true, true, true);
13886         else if (depthonly)
13887         {
13888                 switch (vid.renderpath)
13889                 {
13890                 case RENDERPATH_GL20:
13891                 case RENDERPATH_D3D9:
13892                 case RENDERPATH_D3D10:
13893                 case RENDERPATH_D3D11:
13894                 case RENDERPATH_SOFT:
13895                 case RENDERPATH_GLES2:
13896                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13897                         break;
13898                 case RENDERPATH_GL13:
13899                 case RENDERPATH_GL11:
13900                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13901                         break;
13902                 }
13903         }
13904         else
13905         {
13906                 switch (vid.renderpath)
13907                 {
13908                 case RENDERPATH_GL20:
13909                 case RENDERPATH_D3D9:
13910                 case RENDERPATH_D3D10:
13911                 case RENDERPATH_D3D11:
13912                 case RENDERPATH_SOFT:
13913                 case RENDERPATH_GLES2:
13914                         RSurf_ActiveModelEntity(ent, true, true, false);
13915                         break;
13916                 case RENDERPATH_GL13:
13917                 case RENDERPATH_GL11:
13918                         RSurf_ActiveModelEntity(ent, true, false, false);
13919                         break;
13920                 }
13921         }
13922
13923         surfaces = model->data_surfaces;
13924         update = model->brushq1.lightmapupdateflags;
13925
13926         // update light styles
13927         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13928         {
13929                 model_brush_lightstyleinfo_t *style;
13930                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13931                 {
13932                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13933                         {
13934                                 int *list = style->surfacelist;
13935                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13936                                 for (j = 0;j < style->numsurfaces;j++)
13937                                         update[list[j]] = true;
13938                         }
13939                 }
13940         }
13941
13942         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13943
13944         if (debug)
13945         {
13946                 R_DrawDebugModel();
13947                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13948                 return;
13949         }
13950
13951         rsurface.lightmaptexture = NULL;
13952         rsurface.deluxemaptexture = NULL;
13953         rsurface.uselightmaptexture = false;
13954         rsurface.texture = NULL;
13955         rsurface.rtlight = NULL;
13956         numsurfacelist = 0;
13957         // add visible surfaces to draw list
13958         for (i = 0;i < model->nummodelsurfaces;i++)
13959                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13960         // don't do anything if there were no surfaces
13961         if (!numsurfacelist)
13962         {
13963                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13964                 return;
13965         }
13966         // update lightmaps if needed
13967         if (update)
13968         {
13969                 int updated = 0;
13970                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13971                 {
13972                         if (update[j])
13973                         {
13974                                 updated++;
13975                                 R_BuildLightMap(ent, surfaces + j);
13976                         }
13977                 }
13978         }
13979         if (update)
13980                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13981                         if (update[j])
13982                                 R_BuildLightMap(ent, surfaces + j);
13983         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13984
13985         // add to stats if desired
13986         if (r_speeds.integer && !skysurfaces && !depthonly)
13987         {
13988                 r_refdef.stats.entities_surfaces += numsurfacelist;
13989                 for (j = 0;j < numsurfacelist;j++)
13990                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
13991         }
13992
13993         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13994 }
13995
13996 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
13997 {
13998         static texture_t texture;
13999         static msurface_t surface;
14000         const msurface_t *surfacelist = &surface;
14001
14002         // fake enough texture and surface state to render this geometry
14003
14004         texture.update_lastrenderframe = -1; // regenerate this texture
14005         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14006         texture.currentskinframe = skinframe;
14007         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14008         texture.offsetmapping = OFFSETMAPPING_OFF;
14009         texture.offsetscale = 1;
14010         texture.specularscalemod = 1;
14011         texture.specularpowermod = 1;
14012
14013         surface.texture = &texture;
14014         surface.num_triangles = numtriangles;
14015         surface.num_firsttriangle = firsttriangle;
14016         surface.num_vertices = numvertices;
14017         surface.num_firstvertex = firstvertex;
14018
14019         // now render it
14020         rsurface.texture = R_GetCurrentTexture(surface.texture);
14021         rsurface.lightmaptexture = NULL;
14022         rsurface.deluxemaptexture = NULL;
14023         rsurface.uselightmaptexture = false;
14024         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14025 }
14026
14027 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)
14028 {
14029         static msurface_t surface;
14030         const msurface_t *surfacelist = &surface;
14031
14032         // fake enough texture and surface state to render this geometry
14033         surface.texture = texture;
14034         surface.num_triangles = numtriangles;
14035         surface.num_firsttriangle = firsttriangle;
14036         surface.num_vertices = numvertices;
14037         surface.num_firstvertex = firstvertex;
14038
14039         // now render it
14040         rsurface.texture = R_GetCurrentTexture(surface.texture);
14041         rsurface.lightmaptexture = NULL;
14042         rsurface.deluxemaptexture = NULL;
14043         rsurface.uselightmaptexture = false;
14044         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14045 }