]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
add missing args to Cmd_QuoteString in other files
[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, FOGWIDTH, 1);
516                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 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 "\n"
1076 "\n"
1077 "\n"
1078 "\n"
1079 "// 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"
1080 "\n"
1081 "// fragment shader specific:\n"
1082 "#ifdef FRAGMENT_SHADER\n"
1083 "\n"
1084 "uniform sampler2D Texture_Normal;\n"
1085 "uniform sampler2D Texture_Color;\n"
1086 "uniform sampler2D Texture_Gloss;\n"
1087 "#ifdef USEGLOW\n"
1088 "uniform sampler2D Texture_Glow;\n"
1089 "#endif\n"
1090 "#ifdef USEVERTEXTEXTUREBLEND\n"
1091 "uniform sampler2D Texture_SecondaryNormal;\n"
1092 "uniform sampler2D Texture_SecondaryColor;\n"
1093 "uniform sampler2D Texture_SecondaryGloss;\n"
1094 "#ifdef USEGLOW\n"
1095 "uniform sampler2D Texture_SecondaryGlow;\n"
1096 "#endif\n"
1097 "#endif\n"
1098 "#ifdef USECOLORMAPPING\n"
1099 "uniform sampler2D Texture_Pants;\n"
1100 "uniform sampler2D Texture_Shirt;\n"
1101 "#endif\n"
1102 "#ifdef USEFOG\n"
1103 "#ifdef USEFOGHEIGHTTEXTURE\n"
1104 "uniform sampler2D Texture_FogHeightTexture;\n"
1105 "#endif\n"
1106 "uniform sampler2D Texture_FogMask;\n"
1107 "#endif\n"
1108 "#ifdef USELIGHTMAP\n"
1109 "uniform sampler2D Texture_Lightmap;\n"
1110 "#endif\n"
1111 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1112 "uniform sampler2D Texture_Deluxemap;\n"
1113 "#endif\n"
1114 "#ifdef USEREFLECTION\n"
1115 "uniform sampler2D Texture_Reflection;\n"
1116 "#endif\n"
1117 "\n"
1118 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1119 "uniform sampler2D Texture_ScreenDepth;\n"
1120 "uniform sampler2D Texture_ScreenNormalMap;\n"
1121 "#endif\n"
1122 "#ifdef USEDEFERREDLIGHTMAP\n"
1123 "uniform sampler2D Texture_ScreenDiffuse;\n"
1124 "uniform sampler2D Texture_ScreenSpecular;\n"
1125 "#endif\n"
1126 "\n"
1127 "uniform lowp vec3 Color_Pants;\n"
1128 "uniform lowp vec3 Color_Shirt;\n"
1129 "uniform lowp vec3 FogColor;\n"
1130 "\n"
1131 "#ifdef USEFOG\n"
1132 "uniform highp float FogRangeRecip;\n"
1133 "uniform highp float FogPlaneViewDist;\n"
1134 "uniform highp float FogHeightFade;\n"
1135 "vec3 FogVertex(vec3 surfacecolor)\n"
1136 "{\n"
1137 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1138 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1139 "       float fogfrac;\n"
1140 "#ifdef USEFOGHEIGHTTEXTURE\n"
1141 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1142 "       fogfrac = fogheightpixel.a;\n"
1143 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1144 "#else\n"
1145 "# ifdef USEFOGOUTSIDE\n"
1146 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1147 "# else\n"
1148 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1149 "# endif\n"
1150 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1151 "#endif\n"
1152 "}\n"
1153 "#endif\n"
1154 "\n"
1155 "#ifdef USEOFFSETMAPPING\n"
1156 "uniform mediump float OffsetMapping_Scale;\n"
1157 "vec2 OffsetMapping(vec2 TexCoord)\n"
1158 "{\n"
1159 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1160 "       // 14 sample relief mapping: linear search and then binary search\n"
1161 "       // this basically steps forward a small amount repeatedly until it finds\n"
1162 "       // itself inside solid, then jitters forward and back using decreasing\n"
1163 "       // amounts to find the impact\n"
1164 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1165 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1166 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1167 "       vec3 RT = vec3(TexCoord, 1);\n"
1168 "       OffsetVector *= 0.1;\n"
1169 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1170 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1171 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1172 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1173 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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)          - 0.5);\n"
1179 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1180 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1181 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1182 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1183 "       return RT.xy;\n"
1184 "#else\n"
1185 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1186 "       // this basically moves forward the full distance, and then backs up based\n"
1187 "       // on height of samples\n"
1188 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1189 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1190 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1191 "       TexCoord += OffsetVector;\n"
1192 "       OffsetVector *= 0.5;\n"
1193 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1194 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1195 "       return TexCoord;\n"
1196 "#endif\n"
1197 "}\n"
1198 "#endif // USEOFFSETMAPPING\n"
1199 "\n"
1200 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1201 "uniform sampler2D Texture_Attenuation;\n"
1202 "uniform samplerCube Texture_Cube;\n"
1203 "#endif\n"
1204 "\n"
1205 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1206 "\n"
1207 "#ifdef USESHADOWMAP2D\n"
1208 "# ifdef USESHADOWSAMPLER\n"
1209 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1210 "# else\n"
1211 "uniform sampler2D Texture_ShadowMap2D;\n"
1212 "# endif\n"
1213 "#endif\n"
1214 "\n"
1215 "#ifdef USESHADOWMAPVSDCT\n"
1216 "uniform samplerCube Texture_CubeProjection;\n"
1217 "#endif\n"
1218 "\n"
1219 "#if defined(USESHADOWMAP2D)\n"
1220 "uniform mediump vec2 ShadowMap_TextureScale;\n"
1221 "uniform mediump vec4 ShadowMap_Parameters;\n"
1222 "#endif\n"
1223 "\n"
1224 "#if defined(USESHADOWMAP2D)\n"
1225 "# ifdef USESHADOWMAPORTHO\n"
1226 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1227 "# else\n"
1228 "#  ifdef USESHADOWMAPVSDCT\n"
1229 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1230 "{\n"
1231 "       vec3 adir = abs(dir);\n"
1232 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1233 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1234 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1235 "}\n"
1236 "#  else\n"
1237 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1238 "{\n"
1239 "       vec3 adir = abs(dir);\n"
1240 "       float ma = adir.z;\n"
1241 "       vec4 proj = vec4(dir, 2.5);\n"
1242 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1243 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1244 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1245 "       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"
1246 "}\n"
1247 "#  endif\n"
1248 "# endif\n"
1249 "#endif // defined(USESHADOWMAP2D)\n"
1250 "\n"
1251 "# ifdef USESHADOWMAP2D\n"
1252 "float ShadowMapCompare(vec3 dir)\n"
1253 "{\n"
1254 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1255 "       float f;\n"
1256 "\n"
1257 "#  ifdef USESHADOWSAMPLER\n"
1258 "#    ifdef USESHADOWMAPPCF\n"
1259 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1260 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1261 "       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"
1262 "#    else\n"
1263 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1264 "#    endif\n"
1265 "#  else\n"
1266 "#    ifdef USESHADOWMAPPCF\n"
1267 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1268 "#      ifdef GL_ARB_texture_gather\n"
1269 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1270 "#      else\n"
1271 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1272 "#      endif\n"
1273 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1274 "#      if USESHADOWMAPPCF > 1\n"
1275 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1276 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1277 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1278 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1279 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1280 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1281 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1282 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1283 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1284 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1285 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1286 "       locols.yz += group2.ab;\n"
1287 "       hicols.yz += group8.rg;\n"
1288 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1289 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1290 "                               mix(locols, hicols, offset.y);\n"
1291 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1292 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1293 "       f = dot(cols, vec4(1.0/25.0));\n"
1294 "#      else\n"
1295 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1296 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1297 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1298 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1299 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1300 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1301 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1302 "#      endif\n"
1303 "#     else\n"
1304 "#      ifdef GL_EXT_gpu_shader4\n"
1305 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1306 "#      else\n"
1307 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1308 "#      endif\n"
1309 "#      if USESHADOWMAPPCF > 1\n"
1310 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1311 "       center *= ShadowMap_TextureScale;\n"
1312 "       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"
1313 "       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"
1314 "       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"
1315 "       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"
1316 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1317 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1318 "#      else\n"
1319 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1320 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1321 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1322 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1323 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1324 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1325 "#      endif\n"
1326 "#     endif\n"
1327 "#    else\n"
1328 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1329 "#    endif\n"
1330 "#  endif\n"
1331 "#  ifdef USESHADOWMAPORTHO\n"
1332 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1333 "#  else\n"
1334 "       return f;\n"
1335 "#  endif\n"
1336 "}\n"
1337 "# endif\n"
1338 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1339 "#endif // FRAGMENT_SHADER\n"
1340 "\n"
1341 "\n"
1342 "\n"
1343 "\n"
1344 "#ifdef MODE_DEFERREDGEOMETRY\n"
1345 "#ifdef VERTEX_SHADER\n"
1346 "uniform highp mat4 TexMatrix;\n"
1347 "#ifdef USEVERTEXTEXTUREBLEND\n"
1348 "uniform highp mat4 BackgroundTexMatrix;\n"
1349 "#endif\n"
1350 "uniform highp mat4 ModelViewMatrix;\n"
1351 "void main(void)\n"
1352 "{\n"
1353 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1354 "#ifdef USEVERTEXTEXTUREBLEND\n"
1355 "       VertexColor = Attrib_Color;\n"
1356 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1357 "#endif\n"
1358 "\n"
1359 "       // transform unnormalized eye direction into tangent space\n"
1360 "#ifdef USEOFFSETMAPPING\n"
1361 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1362 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1363 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1364 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1365 "#endif\n"
1366 "\n"
1367 "       VectorS = (ModelViewMatrix * vec4(Attrib_TexCoord1.xyz, 0)).xyz;\n"
1368 "       VectorT = (ModelViewMatrix * vec4(Attrib_TexCoord2.xyz, 0)).xyz;\n"
1369 "       VectorR = (ModelViewMatrix * vec4(Attrib_TexCoord3.xyz, 0)).xyz;\n"
1370 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1371 "}\n"
1372 "#endif // VERTEX_SHADER\n"
1373 "\n"
1374 "#ifdef FRAGMENT_SHADER\n"
1375 "void main(void)\n"
1376 "{\n"
1377 "#ifdef USEOFFSETMAPPING\n"
1378 "       // apply offsetmapping\n"
1379 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1380 "#define TexCoord TexCoordOffset\n"
1381 "#endif\n"
1382 "\n"
1383 "#ifdef USEALPHAKILL\n"
1384 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1385 "               discard;\n"
1386 "#endif\n"
1387 "\n"
1388 "#ifdef USEVERTEXTEXTUREBLEND\n"
1389 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1390 "       float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1391 "       //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
1392 "       //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
1393 "#endif\n"
1394 "\n"
1395 "#ifdef USEVERTEXTEXTUREBLEND\n"
1396 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1397 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1398 "#else\n"
1399 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1400 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1401 "#endif\n"
1402 "\n"
1403 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1404 "}\n"
1405 "#endif // FRAGMENT_SHADER\n"
1406 "#else // !MODE_DEFERREDGEOMETRY\n"
1407 "\n"
1408 "\n"
1409 "\n"
1410 "\n"
1411 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1412 "#ifdef VERTEX_SHADER\n"
1413 "uniform highp mat4 ModelViewMatrix;\n"
1414 "void main(void)\n"
1415 "{\n"
1416 "       ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1417 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1418 "}\n"
1419 "#endif // VERTEX_SHADER\n"
1420 "\n"
1421 "#ifdef FRAGMENT_SHADER\n"
1422 "uniform highp mat4 ViewToLight;\n"
1423 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1424 "uniform highp vec2 ScreenToDepth;\n"
1425 "uniform myhalf3 DeferredColor_Ambient;\n"
1426 "uniform myhalf3 DeferredColor_Diffuse;\n"
1427 "#ifdef USESPECULAR\n"
1428 "uniform myhalf3 DeferredColor_Specular;\n"
1429 "uniform myhalf SpecularPower;\n"
1430 "#endif\n"
1431 "uniform myhalf2 PixelToScreenTexCoord;\n"
1432 "void main(void)\n"
1433 "{\n"
1434 "       // calculate viewspace pixel position\n"
1435 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1436 "       vec3 position;\n"
1437 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1438 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1439 "       // decode viewspace pixel normal\n"
1440 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1441 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1442 "       // surfacenormal = pixel normal in viewspace\n"
1443 "       // LightVector = pixel to light in viewspace\n"
1444 "       // CubeVector = position in lightspace\n"
1445 "       // eyevector = pixel to view in viewspace\n"
1446 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1447 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1448 "#ifdef USEDIFFUSE\n"
1449 "       // calculate diffuse shading\n"
1450 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1451 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1452 "#endif\n"
1453 "#ifdef USESPECULAR\n"
1454 "       // calculate directional shading\n"
1455 "       vec3 eyevector = position * -1.0;\n"
1456 "#  ifdef USEEXACTSPECULARMATH\n"
1457 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1458 "#  else\n"
1459 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1460 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1461 "#  endif\n"
1462 "#endif\n"
1463 "\n"
1464 "#if defined(USESHADOWMAP2D)\n"
1465 "       fade *= ShadowMapCompare(CubeVector);\n"
1466 "#endif\n"
1467 "\n"
1468 "#ifdef USEDIFFUSE\n"
1469 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1470 "#else\n"
1471 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1472 "#endif\n"
1473 "#ifdef USESPECULAR\n"
1474 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1475 "#else\n"
1476 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1477 "#endif\n"
1478 "\n"
1479 "# ifdef USECUBEFILTER\n"
1480 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1481 "       gl_FragData[0].rgb *= cubecolor;\n"
1482 "       gl_FragData[1].rgb *= cubecolor;\n"
1483 "# endif\n"
1484 "}\n"
1485 "#endif // FRAGMENT_SHADER\n"
1486 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1487 "\n"
1488 "\n"
1489 "\n"
1490 "\n"
1491 "#ifdef VERTEX_SHADER\n"
1492 "uniform highp mat4 TexMatrix;\n"
1493 "#ifdef USEVERTEXTEXTUREBLEND\n"
1494 "uniform highp mat4 BackgroundTexMatrix;\n"
1495 "#endif\n"
1496 "#ifdef MODE_LIGHTSOURCE\n"
1497 "uniform highp mat4 ModelToLight;\n"
1498 "#endif\n"
1499 "#ifdef USESHADOWMAPORTHO\n"
1500 "uniform highp mat4 ShadowMapMatrix;\n"
1501 "#endif\n"
1502 "void main(void)\n"
1503 "{\n"
1504 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1505 "       VertexColor = Attrib_Color;\n"
1506 "#endif\n"
1507 "       // copy the surface texcoord\n"
1508 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1509 "#ifdef USEVERTEXTEXTUREBLEND\n"
1510 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1511 "#endif\n"
1512 "#ifdef USELIGHTMAP\n"
1513 "       TexCoordLightmap = vec2(Attrib_TexCoord4);\n"
1514 "#endif\n"
1515 "\n"
1516 "#ifdef MODE_LIGHTSOURCE\n"
1517 "       // transform vertex position into light attenuation/cubemap space\n"
1518 "       // (-1 to +1 across the light box)\n"
1519 "       CubeVector = vec3(ModelToLight * Attrib_Position);\n"
1520 "\n"
1521 "# ifdef USEDIFFUSE\n"
1522 "       // transform unnormalized light direction into tangent space\n"
1523 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1524 "       //  normalize it per pixel)\n"
1525 "       vec3 lightminusvertex = LightPosition - Attrib_Position.xyz;\n"
1526 "       LightVector.x = dot(lightminusvertex, Attrib_TexCoord1.xyz);\n"
1527 "       LightVector.y = dot(lightminusvertex, Attrib_TexCoord2.xyz);\n"
1528 "       LightVector.z = dot(lightminusvertex, Attrib_TexCoord3.xyz);\n"
1529 "# endif\n"
1530 "#endif\n"
1531 "\n"
1532 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1533 "       LightVector.x = dot(LightDir, Attrib_TexCoord1.xyz);\n"
1534 "       LightVector.y = dot(LightDir, Attrib_TexCoord2.xyz);\n"
1535 "       LightVector.z = dot(LightDir, Attrib_TexCoord3.xyz);\n"
1536 "#endif\n"
1537 "\n"
1538 "       // transform unnormalized eye direction into tangent space\n"
1539 "#ifdef USEEYEVECTOR\n"
1540 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1541 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1542 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1543 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1544 "#endif\n"
1545 "\n"
1546 "#ifdef USEFOG\n"
1547 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - Attrib_Position.xyz;\n"
1548 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, Attrib_Position);\n"
1549 "#endif\n"
1550 "\n"
1551 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1552 "       VectorS = Attrib_TexCoord1.xyz;\n"
1553 "       VectorT = Attrib_TexCoord2.xyz;\n"
1554 "       VectorR = Attrib_TexCoord3.xyz;\n"
1555 "#endif\n"
1556 "\n"
1557 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1558 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1559 "\n"
1560 "#ifdef USESHADOWMAPORTHO\n"
1561 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1562 "#endif\n"
1563 "\n"
1564 "#ifdef USEREFLECTION\n"
1565 "       ModelViewProjectionPosition = gl_Position;\n"
1566 "#endif\n"
1567 "}\n"
1568 "#endif // VERTEX_SHADER\n"
1569 "\n"
1570 "\n"
1571 "\n"
1572 "\n"
1573 "#ifdef FRAGMENT_SHADER\n"
1574 "#ifdef USEDEFERREDLIGHTMAP\n"
1575 "uniform myhalf2 PixelToScreenTexCoord;\n"
1576 "uniform myhalf3 DeferredMod_Diffuse;\n"
1577 "uniform myhalf3 DeferredMod_Specular;\n"
1578 "#endif\n"
1579 "uniform myhalf3 Color_Ambient;\n"
1580 "uniform myhalf3 Color_Diffuse;\n"
1581 "uniform myhalf3 Color_Specular;\n"
1582 "uniform myhalf SpecularPower;\n"
1583 "#ifdef USEGLOW\n"
1584 "uniform myhalf3 Color_Glow;\n"
1585 "#endif\n"
1586 "uniform myhalf Alpha;\n"
1587 "#ifdef USEREFLECTION\n"
1588 "uniform mediump vec4 DistortScaleRefractReflect;\n"
1589 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
1590 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
1591 "uniform lowp vec4 ReflectColor;\n"
1592 "#endif\n"
1593 "#ifdef USEREFLECTCUBE\n"
1594 "uniform highp mat4 ModelToReflectCube;\n"
1595 "uniform sampler2D Texture_ReflectMask;\n"
1596 "uniform samplerCube Texture_ReflectCube;\n"
1597 "#endif\n"
1598 "#ifdef MODE_LIGHTDIRECTION\n"
1599 "uniform myhalf3 LightColor;\n"
1600 "#endif\n"
1601 "#ifdef MODE_LIGHTSOURCE\n"
1602 "uniform myhalf3 LightColor;\n"
1603 "#endif\n"
1604 "void main(void)\n"
1605 "{\n"
1606 "#ifdef USEOFFSETMAPPING\n"
1607 "       // apply offsetmapping\n"
1608 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1609 "#define TexCoord TexCoordOffset\n"
1610 "#endif\n"
1611 "\n"
1612 "       // combine the diffuse textures (base, pants, shirt)\n"
1613 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1614 "#ifdef USEALPHAKILL\n"
1615 "       if (color.a < 0.5)\n"
1616 "               discard;\n"
1617 "#endif\n"
1618 "       color.a *= Alpha;\n"
1619 "#ifdef USECOLORMAPPING\n"
1620 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1621 "#endif\n"
1622 "#ifdef USEVERTEXTEXTUREBLEND\n"
1623 "       myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1624 "       //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
1625 "       //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
1626 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1627 "       color.a = 1.0;\n"
1628 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1629 "#endif\n"
1630 "\n"
1631 "       // get the surface normal\n"
1632 "#ifdef USEVERTEXTEXTUREBLEND\n"
1633 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1634 "#else\n"
1635 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1636 "#endif\n"
1637 "\n"
1638 "       // get the material colors\n"
1639 "       myhalf3 diffusetex = color.rgb;\n"
1640 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1641 "# ifdef USEVERTEXTEXTUREBLEND\n"
1642 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1643 "# else\n"
1644 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1645 "# endif\n"
1646 "#endif\n"
1647 "\n"
1648 "#ifdef USEREFLECTCUBE\n"
1649 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1650 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1651 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1652 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1653 "#endif\n"
1654 "\n"
1655 "\n"
1656 "\n"
1657 "\n"
1658 "#ifdef MODE_LIGHTSOURCE\n"
1659 "       // light source\n"
1660 "#ifdef USEDIFFUSE\n"
1661 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1662 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1663 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1664 "#ifdef USESPECULAR\n"
1665 "#ifdef USEEXACTSPECULARMATH\n"
1666 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1667 "#else\n"
1668 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1669 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1670 "#endif\n"
1671 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1672 "#endif\n"
1673 "#else\n"
1674 "       color.rgb = diffusetex * Color_Ambient;\n"
1675 "#endif\n"
1676 "       color.rgb *= LightColor;\n"
1677 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1678 "#if defined(USESHADOWMAP2D)\n"
1679 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1680 "#endif\n"
1681 "# ifdef USECUBEFILTER\n"
1682 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1683 "# endif\n"
1684 "#endif // MODE_LIGHTSOURCE\n"
1685 "\n"
1686 "\n"
1687 "\n"
1688 "\n"
1689 "#ifdef MODE_LIGHTDIRECTION\n"
1690 "#define SHADING\n"
1691 "#ifdef USEDIFFUSE\n"
1692 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1693 "#endif\n"
1694 "#define lightcolor LightColor\n"
1695 "#endif // MODE_LIGHTDIRECTION\n"
1696 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1697 "#define SHADING\n"
1698 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1699 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1700 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1701 "       // convert modelspace light vector to tangentspace\n"
1702 "       myhalf3 lightnormal;\n"
1703 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1704 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1705 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1706 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1707 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1708 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1709 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1710 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1711 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1712 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1713 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1714 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1715 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1716 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1717 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1718 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1719 "#define SHADING\n"
1720 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1721 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1722 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1723 "#endif\n"
1724 "\n"
1725 "\n"
1726 "\n"
1727 "\n"
1728 "#ifdef MODE_FAKELIGHT\n"
1729 "#define SHADING\n"
1730 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1731 "myhalf3 lightcolor = myhalf3(1.0);\n"
1732 "#endif // MODE_FAKELIGHT\n"
1733 "\n"
1734 "\n"
1735 "\n"
1736 "\n"
1737 "#ifdef MODE_LIGHTMAP\n"
1738 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1739 "#endif // MODE_LIGHTMAP\n"
1740 "#ifdef MODE_VERTEXCOLOR\n"
1741 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
1742 "#endif // MODE_VERTEXCOLOR\n"
1743 "#ifdef MODE_FLATCOLOR\n"
1744 "       color.rgb = diffusetex * Color_Ambient;\n"
1745 "#endif // MODE_FLATCOLOR\n"
1746 "\n"
1747 "\n"
1748 "\n"
1749 "\n"
1750 "#ifdef SHADING\n"
1751 "# ifdef USEDIFFUSE\n"
1752 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1753 "#  ifdef USESPECULAR\n"
1754 "#   ifdef USEEXACTSPECULARMATH\n"
1755 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1756 "#   else\n"
1757 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1758 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1759 "#   endif\n"
1760 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1761 "#  else\n"
1762 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1763 "#  endif\n"
1764 "# else\n"
1765 "       color.rgb = diffusetex * Color_Ambient;\n"
1766 "# endif\n"
1767 "#endif\n"
1768 "\n"
1769 "#ifdef USESHADOWMAPORTHO\n"
1770 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1771 "#endif\n"
1772 "\n"
1773 "#ifdef USEDEFERREDLIGHTMAP\n"
1774 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1775 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1776 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1777 "#endif\n"
1778 "\n"
1779 "#ifdef USEGLOW\n"
1780 "#ifdef USEVERTEXTEXTUREBLEND\n"
1781 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1782 "#else\n"
1783 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1784 "#endif\n"
1785 "#endif\n"
1786 "\n"
1787 "#ifdef USEFOG\n"
1788 "       color.rgb = FogVertex(color.rgb);\n"
1789 "#endif\n"
1790 "\n"
1791 "       // 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"
1792 "#ifdef USEREFLECTION\n"
1793 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1794 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1795 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1796 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1797 "       // FIXME temporary hack to detect the case that the reflection\n"
1798 "       // gets blackened at edges due to leaving the area that contains actual\n"
1799 "       // content.\n"
1800 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1801 "       // 'appening.\n"
1802 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1803 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1804 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1805 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1806 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1807 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1808 "#endif\n"
1809 "\n"
1810 "       gl_FragColor = vec4(color);\n"
1811 "}\n"
1812 "#endif // FRAGMENT_SHADER\n"
1813 "\n"
1814 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1815 "#endif // !MODE_DEFERREDGEOMETRY\n"
1816 "#endif // !MODE_WATER\n"
1817 "#endif // !MODE_REFRACTION\n"
1818 "#endif // !MODE_BLOOMBLUR\n"
1819 "#endif // !MODE_GENERIC\n"
1820 "#endif // !MODE_POSTPROCESS\n"
1821 "#endif // !MODE_SHOWDEPTH\n"
1822 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1823 ;
1824
1825 /*
1826 =========================================================================================================================================================
1827
1828
1829
1830 =========================================================================================================================================================
1831
1832
1833
1834 =========================================================================================================================================================
1835
1836
1837
1838 =========================================================================================================================================================
1839
1840
1841
1842 =========================================================================================================================================================
1843
1844
1845
1846 =========================================================================================================================================================
1847
1848
1849
1850 =========================================================================================================================================================
1851 */
1852
1853 const char *builtinhlslshaderstring =
1854 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1855 "// written by Forest 'LordHavoc' Hale\n"
1856 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1857 "\n"
1858 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1859 "#if defined(USEREFLECTION)\n"
1860 "#undef USESHADOWMAPORTHO\n"
1861 "#endif\n"
1862 "\n"
1863 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1864 "# define USEFOG\n"
1865 "#endif\n"
1866 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1867 "#define USELIGHTMAP\n"
1868 "#endif\n"
1869 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1870 "#define USEEYEVECTOR\n"
1871 "#endif\n"
1872 "\n"
1873 "#ifdef FRAGMENT_SHADER\n"
1874 "#ifdef HLSL\n"
1875 "//#undef USESHADOWMAPPCF\n"
1876 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1877 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1878 "#else\n"
1879 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1880 "#endif\n"
1881 "#endif\n"
1882 "\n"
1883 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1884 "#ifdef VERTEX_SHADER\n"
1885 "void main\n"
1886 "(\n"
1887 "float4 gl_Vertex : POSITION,\n"
1888 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1889 "out float4 gl_Position : POSITION,\n"
1890 "out float Depth : TEXCOORD0\n"
1891 ")\n"
1892 "{\n"
1893 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1894 "       Depth = gl_Position.z;\n"
1895 "}\n"
1896 "#endif\n"
1897 "\n"
1898 "#ifdef FRAGMENT_SHADER\n"
1899 "void main\n"
1900 "(\n"
1901 "float Depth : TEXCOORD0,\n"
1902 "out float4 gl_FragColor : COLOR\n"
1903 ")\n"
1904 "{\n"
1905 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1906 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1907 "       temp.yz -= floor(temp.yz);\n"
1908 "       gl_FragColor = temp;\n"
1909 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1910 "}\n"
1911 "#endif\n"
1912 "#else // !MODE_DEPTH_ORSHADOW\n"
1913 "\n"
1914 "\n"
1915 "\n"
1916 "\n"
1917 "#ifdef MODE_SHOWDEPTH\n"
1918 "#ifdef VERTEX_SHADER\n"
1919 "void main\n"
1920 "(\n"
1921 "float4 gl_Vertex : POSITION,\n"
1922 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1923 "out float4 gl_Position : POSITION,\n"
1924 "out float4 gl_FrontColor : COLOR0\n"
1925 ")\n"
1926 "{\n"
1927 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1928 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1929 "}\n"
1930 "#endif\n"
1931 "\n"
1932 "#ifdef FRAGMENT_SHADER\n"
1933 "void main\n"
1934 "(\n"
1935 "float4 gl_FrontColor : COLOR0,\n"
1936 "out float4 gl_FragColor : COLOR\n"
1937 ")\n"
1938 "{\n"
1939 "       gl_FragColor = gl_FrontColor;\n"
1940 "}\n"
1941 "#endif\n"
1942 "#else // !MODE_SHOWDEPTH\n"
1943 "\n"
1944 "\n"
1945 "\n"
1946 "\n"
1947 "#ifdef MODE_POSTPROCESS\n"
1948 "\n"
1949 "#ifdef VERTEX_SHADER\n"
1950 "void main\n"
1951 "(\n"
1952 "float4 gl_Vertex : POSITION,\n"
1953 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1954 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1955 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1956 "out float4 gl_Position : POSITION,\n"
1957 "out float2 TexCoord1 : TEXCOORD0,\n"
1958 "out float2 TexCoord2 : TEXCOORD1\n"
1959 ")\n"
1960 "{\n"
1961 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1962 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1963 "#ifdef USEBLOOM\n"
1964 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1965 "#endif\n"
1966 "}\n"
1967 "#endif\n"
1968 "\n"
1969 "#ifdef FRAGMENT_SHADER\n"
1970 "void main\n"
1971 "(\n"
1972 "float2 TexCoord1 : TEXCOORD0,\n"
1973 "float2 TexCoord2 : TEXCOORD1,\n"
1974 "uniform sampler Texture_First : register(s0),\n"
1975 "#ifdef USEBLOOM\n"
1976 "uniform sampler Texture_Second : register(s1),\n"
1977 "#endif\n"
1978 "#ifdef USEGAMMARAMPS\n"
1979 "uniform sampler Texture_GammaRamps : register(s2),\n"
1980 "#endif\n"
1981 "#ifdef USESATURATION\n"
1982 "uniform float Saturation : register(c30),\n"
1983 "#endif\n"
1984 "#ifdef USEVIEWTINT\n"
1985 "uniform float4 ViewTintColor : register(c41),\n"
1986 "#endif\n"
1987 "uniform float4 UserVec1 : register(c37),\n"
1988 "uniform float4 UserVec2 : register(c38),\n"
1989 "uniform float4 UserVec3 : register(c39),\n"
1990 "uniform float4 UserVec4 : register(c40),\n"
1991 "uniform float ClientTime : register(c2),\n"
1992 "uniform float2 PixelSize : register(c25),\n"
1993 "uniform float4 BloomColorSubtract : register(c43),\n"
1994 "out float4 gl_FragColor : COLOR\n"
1995 ")\n"
1996 "{\n"
1997 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1998 "#ifdef USEBLOOM\n"
1999 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2000 "#endif\n"
2001 "#ifdef USEVIEWTINT\n"
2002 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2003 "#endif\n"
2004 "\n"
2005 "#ifdef USEPOSTPROCESSING\n"
2006 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2007 "// 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"
2008 "       float sobel = 1.0;\n"
2009 "       // float2 ts = textureSize(Texture_First, 0);\n"
2010 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
2011 "       float2 px = PixelSize;\n"
2012 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2013 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
2014 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2015 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2016 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
2017 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2018 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2019 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
2020 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2021 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2022 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
2023 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2024 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2025 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2026 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2027 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2028 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2029 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2030 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2031 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2032 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2033 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2034 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2035 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2036 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2037 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2038 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2039 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2040 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2041 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2042 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2043 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2044 "#endif\n"
2045 "\n"
2046 "#ifdef USESATURATION\n"
2047 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2048 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2049 "       // 'vampire sight' effect, wheres red is compensated\n"
2050 "       #ifdef SATURATION_REDCOMPENSATE\n"
2051 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2052 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2053 "               gl_FragColor.r += r;\n"
2054 "       #else\n"
2055 "               // normal desaturation\n"
2056 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2057 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2058 "       #endif\n"
2059 "#endif\n"
2060 "\n"
2061 "#ifdef USEGAMMARAMPS\n"
2062 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2063 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2064 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2065 "#endif\n"
2066 "}\n"
2067 "#endif\n"
2068 "#else // !MODE_POSTPROCESS\n"
2069 "\n"
2070 "\n"
2071 "\n"
2072 "\n"
2073 "#ifdef MODE_GENERIC\n"
2074 "#ifdef VERTEX_SHADER\n"
2075 "void main\n"
2076 "(\n"
2077 "float4 gl_Vertex : POSITION,\n"
2078 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2079 "float4 gl_Color : COLOR0,\n"
2080 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2081 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2082 "out float4 gl_Position : POSITION,\n"
2083 "#ifdef USEDIFFUSE\n"
2084 "out float2 TexCoord1 : TEXCOORD0,\n"
2085 "#endif\n"
2086 "#ifdef USESPECULAR\n"
2087 "out float2 TexCoord2 : TEXCOORD1,\n"
2088 "#endif\n"
2089 "out float4 gl_FrontColor : COLOR\n"
2090 ")\n"
2091 "{\n"
2092 "#ifdef HLSL\n"
2093 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2094 "#else\n"
2095 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2096 "#endif\n"
2097 "#ifdef USEDIFFUSE\n"
2098 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2099 "#endif\n"
2100 "#ifdef USESPECULAR\n"
2101 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2102 "#endif\n"
2103 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2104 "}\n"
2105 "#endif\n"
2106 "\n"
2107 "#ifdef FRAGMENT_SHADER\n"
2108 "\n"
2109 "void main\n"
2110 "(\n"
2111 "float4 gl_FrontColor : COLOR0,\n"
2112 "float2 TexCoord1 : TEXCOORD0,\n"
2113 "float2 TexCoord2 : TEXCOORD1,\n"
2114 "#ifdef USEDIFFUSE\n"
2115 "uniform sampler Texture_First : register(s0),\n"
2116 "#endif\n"
2117 "#ifdef USESPECULAR\n"
2118 "uniform sampler Texture_Second : register(s1),\n"
2119 "#endif\n"
2120 "out float4 gl_FragColor : COLOR\n"
2121 ")\n"
2122 "{\n"
2123 "#ifdef USEVIEWTINT\n"
2124 "       gl_FragColor = gl_FrontColor;\n"
2125 "#else\n"
2126 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2127 "#endif\n"
2128 "#ifdef USEDIFFUSE\n"
2129 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2130 "#endif\n"
2131 "\n"
2132 "#ifdef USESPECULAR\n"
2133 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2134 "# ifdef USECOLORMAPPING\n"
2135 "       gl_FragColor *= tex2;\n"
2136 "# endif\n"
2137 "# ifdef USEGLOW\n"
2138 "       gl_FragColor += tex2;\n"
2139 "# endif\n"
2140 "# ifdef USEVERTEXTEXTUREBLEND\n"
2141 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2142 "# endif\n"
2143 "#endif\n"
2144 "}\n"
2145 "#endif\n"
2146 "#else // !MODE_GENERIC\n"
2147 "\n"
2148 "\n"
2149 "\n"
2150 "\n"
2151 "#ifdef MODE_BLOOMBLUR\n"
2152 "#ifdef VERTEX_SHADER\n"
2153 "void main\n"
2154 "(\n"
2155 "float4 gl_Vertex : POSITION,\n"
2156 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2157 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2158 "out float4 gl_Position : POSITION,\n"
2159 "out float2 TexCoord : TEXCOORD0\n"
2160 ")\n"
2161 "{\n"
2162 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2163 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2164 "}\n"
2165 "#endif\n"
2166 "\n"
2167 "#ifdef FRAGMENT_SHADER\n"
2168 "\n"
2169 "void main\n"
2170 "(\n"
2171 "float2 TexCoord : TEXCOORD0,\n"
2172 "uniform sampler Texture_First : register(s0),\n"
2173 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2174 "out float4 gl_FragColor : COLOR\n"
2175 ")\n"
2176 "{\n"
2177 "       int i;\n"
2178 "       float2 tc = TexCoord;\n"
2179 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2180 "       tc += BloomBlur_Parameters.xy;\n"
2181 "       for (i = 1;i < SAMPLES;i++)\n"
2182 "       {\n"
2183 "               color += tex2D(Texture_First, tc).rgb;\n"
2184 "               tc += BloomBlur_Parameters.xy;\n"
2185 "       }\n"
2186 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2187 "}\n"
2188 "#endif\n"
2189 "#else // !MODE_BLOOMBLUR\n"
2190 "#ifdef MODE_REFRACTION\n"
2191 "#ifdef VERTEX_SHADER\n"
2192 "void main\n"
2193 "(\n"
2194 "float4 gl_Vertex : POSITION,\n"
2195 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2196 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2197 "uniform float4x4 TexMatrix : register(c0),\n"
2198 "uniform float3 EyePosition : register(c24),\n"
2199 "out float4 gl_Position : POSITION,\n"
2200 "out float2 TexCoord : TEXCOORD0,\n"
2201 "out float3 EyeVector : TEXCOORD1,\n"
2202 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2203 ")\n"
2204 "{\n"
2205 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2206 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2207 "       ModelViewProjectionPosition = gl_Position;\n"
2208 "}\n"
2209 "#endif\n"
2210 "\n"
2211 "#ifdef FRAGMENT_SHADER\n"
2212 "void main\n"
2213 "(\n"
2214 "float2 TexCoord : TEXCOORD0,\n"
2215 "float3 EyeVector : TEXCOORD1,\n"
2216 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2217 "uniform sampler Texture_Normal : register(s0),\n"
2218 "uniform sampler Texture_Refraction : register(s3),\n"
2219 "uniform sampler Texture_Reflection : register(s7),\n"
2220 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2221 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2222 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2223 "uniform float4 RefractColor : register(c29),\n"
2224 "out float4 gl_FragColor : COLOR\n"
2225 ")\n"
2226 "{\n"
2227 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2228 "       //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"
2229 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2230 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2231 "       // FIXME temporary hack to detect the case that the reflection\n"
2232 "       // gets blackened at edges due to leaving the area that contains actual\n"
2233 "       // content.\n"
2234 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2235 "       // 'appening.\n"
2236 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2237 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2238 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2239 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2240 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2241 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2242 "}\n"
2243 "#endif\n"
2244 "#else // !MODE_REFRACTION\n"
2245 "\n"
2246 "\n"
2247 "\n"
2248 "\n"
2249 "#ifdef MODE_WATER\n"
2250 "#ifdef VERTEX_SHADER\n"
2251 "\n"
2252 "void main\n"
2253 "(\n"
2254 "float4 gl_Vertex : POSITION,\n"
2255 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2256 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2257 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2258 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2259 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2260 "uniform float4x4 TexMatrix : register(c0),\n"
2261 "uniform float3 EyePosition : register(c24),\n"
2262 "out float4 gl_Position : POSITION,\n"
2263 "out float2 TexCoord : TEXCOORD0,\n"
2264 "out float3 EyeVector : TEXCOORD1,\n"
2265 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2266 ")\n"
2267 "{\n"
2268 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2269 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2270 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2271 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2272 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2273 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2274 "       ModelViewProjectionPosition = gl_Position;\n"
2275 "}\n"
2276 "#endif\n"
2277 "\n"
2278 "#ifdef FRAGMENT_SHADER\n"
2279 "void main\n"
2280 "(\n"
2281 "float2 TexCoord : TEXCOORD0,\n"
2282 "float3 EyeVector : TEXCOORD1,\n"
2283 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2284 "uniform sampler Texture_Normal : register(s0),\n"
2285 "uniform sampler Texture_Refraction : register(s3),\n"
2286 "uniform sampler Texture_Reflection : register(s7),\n"
2287 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2288 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2289 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2290 "uniform float4 RefractColor : register(c29),\n"
2291 "uniform float4 ReflectColor : register(c26),\n"
2292 "uniform float ReflectFactor : register(c27),\n"
2293 "uniform float ReflectOffset : register(c28),\n"
2294 "out float4 gl_FragColor : COLOR\n"
2295 ")\n"
2296 "{\n"
2297 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2298 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2299 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2300 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2301 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2302 "       // FIXME temporary hack to detect the case that the reflection\n"
2303 "       // gets blackened at edges due to leaving the area that contains actual\n"
2304 "       // content.\n"
2305 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2306 "       // 'appening.\n"
2307 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2308 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2309 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2310 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2311 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2312 "       f  = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2313 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2314 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2315 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2316 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2317 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2318 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2319 "}\n"
2320 "#endif\n"
2321 "#else // !MODE_WATER\n"
2322 "\n"
2323 "\n"
2324 "\n"
2325 "\n"
2326 "// 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"
2327 "\n"
2328 "// fragment shader specific:\n"
2329 "#ifdef FRAGMENT_SHADER\n"
2330 "\n"
2331 "#ifdef USEFOG\n"
2332 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2333 "{\n"
2334 "       float fogfrac;\n"
2335 "#ifdef USEFOGHEIGHTTEXTURE\n"
2336 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2337 "       fogfrac = fogheightpixel.a;\n"
2338 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2339 "#else\n"
2340 "# ifdef USEFOGOUTSIDE\n"
2341 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2342 "# else\n"
2343 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2344 "# endif\n"
2345 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2346 "#endif\n"
2347 "}\n"
2348 "#endif\n"
2349 "\n"
2350 "#ifdef USEOFFSETMAPPING\n"
2351 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2352 "{\n"
2353 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2354 "       // 14 sample relief mapping: linear search and then binary search\n"
2355 "       // this basically steps forward a small amount repeatedly until it finds\n"
2356 "       // itself inside solid, then jitters forward and back using decreasing\n"
2357 "       // amounts to find the impact\n"
2358 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2359 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2360 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2361 "       float3 RT = float3(TexCoord, 1);\n"
2362 "       OffsetVector *= 0.1;\n"
2363 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2364 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2365 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2366 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2367 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2368 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2369 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2370 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2371 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2372 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2373 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2374 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2375 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2376 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2377 "       return RT.xy;\n"
2378 "#else\n"
2379 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2380 "       // this basically moves forward the full distance, and then backs up based\n"
2381 "       // on height of samples\n"
2382 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2383 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2384 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2385 "       TexCoord += OffsetVector;\n"
2386 "       OffsetVector *= 0.333;\n"
2387 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2388 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2389 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2390 "       return TexCoord;\n"
2391 "#endif\n"
2392 "}\n"
2393 "#endif // USEOFFSETMAPPING\n"
2394 "\n"
2395 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2396 "#if defined(USESHADOWMAP2D)\n"
2397 "# ifdef USESHADOWMAPORTHO\n"
2398 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2399 "# else\n"
2400 "#  ifdef USESHADOWMAPVSDCT\n"
2401 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2402 "{\n"
2403 "       float3 adir = abs(dir);\n"
2404 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2405 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2406 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2407 "}\n"
2408 "#  else\n"
2409 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2410 "{\n"
2411 "       float3 adir = abs(dir);\n"
2412 "       float ma = adir.z;\n"
2413 "       float4 proj = float4(dir, 2.5);\n"
2414 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2415 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2416 "#ifdef HLSL\n"
2417 "       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"
2418 "#else\n"
2419 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2420 "       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"
2421 "#endif\n"
2422 "}\n"
2423 "#  endif\n"
2424 "# endif\n"
2425 "#endif // defined(USESHADOWMAP2D)\n"
2426 "\n"
2427 "# ifdef USESHADOWMAP2D\n"
2428 "#ifdef USESHADOWMAPVSDCT\n"
2429 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2430 "#else\n"
2431 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2432 "#endif\n"
2433 "{\n"
2434 "#ifdef USESHADOWMAPVSDCT\n"
2435 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2436 "#else\n"
2437 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2438 "#endif\n"
2439 "       float f;\n"
2440 "\n"
2441 "#  ifdef USESHADOWSAMPLER\n"
2442 "#    ifdef USESHADOWMAPPCF\n"
2443 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2444 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2445 "       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"
2446 "#    else\n"
2447 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2448 "#    endif\n"
2449 "#  else\n"
2450 "#    ifdef USESHADOWMAPPCF\n"
2451 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2452 "#      ifdef GL_ARB_texture_gather\n"
2453 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2454 "#      else\n"
2455 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2456 "#      endif\n"
2457 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2458 "#      if USESHADOWMAPPCF > 1\n"
2459 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2460 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2461 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2462 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2463 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2464 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2465 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2466 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2467 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2468 "       float4 locols = float4(group1.ab, group3.ab);\n"
2469 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2470 "       locols.yz += group2.ab;\n"
2471 "       hicols.yz += group8.rg;\n"
2472 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2473 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2474 "                               lerp(locols, hicols, offset.y);\n"
2475 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2476 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2477 "       f = dot(cols, float4(1.0/25.0));\n"
2478 "#      else\n"
2479 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2480 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2481 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2482 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2483 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2484 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2485 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2486 "#      endif\n"
2487 "#     else\n"
2488 "#      ifdef GL_EXT_gpu_shader4\n"
2489 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2490 "#      else\n"
2491 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2492 "#      endif\n"
2493 "#      if USESHADOWMAPPCF > 1\n"
2494 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2495 "       center *= ShadowMap_TextureScale;\n"
2496 "       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"
2497 "       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"
2498 "       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"
2499 "       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"
2500 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2501 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2502 "#      else\n"
2503 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2504 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2505 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2506 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2507 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2508 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2509 "#      endif\n"
2510 "#     endif\n"
2511 "#    else\n"
2512 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2513 "#    endif\n"
2514 "#  endif\n"
2515 "#  ifdef USESHADOWMAPORTHO\n"
2516 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2517 "#  else\n"
2518 "       return f;\n"
2519 "#  endif\n"
2520 "}\n"
2521 "# endif\n"
2522 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2523 "#endif // FRAGMENT_SHADER\n"
2524 "\n"
2525 "\n"
2526 "\n"
2527 "\n"
2528 "#ifdef MODE_DEFERREDGEOMETRY\n"
2529 "#ifdef VERTEX_SHADER\n"
2530 "void main\n"
2531 "(\n"
2532 "float4 gl_Vertex : POSITION,\n"
2533 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2534 "#ifdef USEVERTEXTEXTUREBLEND\n"
2535 "float4 gl_Color : COLOR0,\n"
2536 "#endif\n"
2537 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2538 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2539 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2540 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2541 "uniform float4x4 TexMatrix : register(c0),\n"
2542 "#ifdef USEVERTEXTEXTUREBLEND\n"
2543 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2544 "#endif\n"
2545 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2546 "#ifdef USEOFFSETMAPPING\n"
2547 "uniform float3 EyePosition : register(c24),\n"
2548 "#endif\n"
2549 "out float4 gl_Position : POSITION,\n"
2550 "#ifdef USEVERTEXTEXTUREBLEND\n"
2551 "out float4 gl_FrontColor : COLOR,\n"
2552 "#endif\n"
2553 "out float4 TexCoordBoth : TEXCOORD0,\n"
2554 "#ifdef USEOFFSETMAPPING\n"
2555 "out float3 EyeVector : TEXCOORD2,\n"
2556 "#endif\n"
2557 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2558 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2559 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2560 ")\n"
2561 "{\n"
2562 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2563 "#ifdef USEVERTEXTEXTUREBLEND\n"
2564 "#ifdef HLSL\n"
2565 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2566 "#else\n"
2567 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2568 "#endif\n"
2569 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2570 "#endif\n"
2571 "\n"
2572 "       // transform unnormalized eye direction into tangent space\n"
2573 "#ifdef USEOFFSETMAPPING\n"
2574 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2575 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2576 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2577 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2578 "#endif\n"
2579 "\n"
2580 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2581 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2582 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2583 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2584 "       VectorR.w = gl_Position.z;\n"
2585 "}\n"
2586 "#endif // VERTEX_SHADER\n"
2587 "\n"
2588 "#ifdef FRAGMENT_SHADER\n"
2589 "void main\n"
2590 "(\n"
2591 "float4 TexCoordBoth : TEXCOORD0,\n"
2592 "float3 EyeVector : TEXCOORD2,\n"
2593 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2594 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2595 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2596 "uniform sampler Texture_Normal : register(s0),\n"
2597 "#ifdef USEALPHAKILL\n"
2598 "uniform sampler Texture_Color : register(s1),\n"
2599 "#endif\n"
2600 "uniform sampler Texture_Gloss : register(s2),\n"
2601 "#ifdef USEVERTEXTEXTUREBLEND\n"
2602 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2603 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2604 "#endif\n"
2605 "#ifdef USEOFFSETMAPPING\n"
2606 "uniform float OffsetMapping_Scale : register(c24),\n"
2607 "#endif\n"
2608 "uniform half SpecularPower : register(c36),\n"
2609 "#ifdef HLSL\n"
2610 "out float4 gl_FragData0 : COLOR0,\n"
2611 "out float4 gl_FragData1 : COLOR1\n"
2612 "#else\n"
2613 "out float4 gl_FragColor : COLOR\n"
2614 "#endif\n"
2615 ")\n"
2616 "{\n"
2617 "       float2 TexCoord = TexCoordBoth.xy;\n"
2618 "#ifdef USEOFFSETMAPPING\n"
2619 "       // apply offsetmapping\n"
2620 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2621 "#define TexCoord TexCoordOffset\n"
2622 "#endif\n"
2623 "\n"
2624 "#ifdef USEALPHAKILL\n"
2625 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2626 "               discard;\n"
2627 "#endif\n"
2628 "\n"
2629 "#ifdef USEVERTEXTEXTUREBLEND\n"
2630 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2631 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2632 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2633 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2634 "#endif\n"
2635 "\n"
2636 "#ifdef USEVERTEXTEXTUREBLEND\n"
2637 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2638 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2639 "#else\n"
2640 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2641 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2642 "#endif\n"
2643 "\n"
2644 "#ifdef HLSL\n"
2645 "       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"
2646 "       float Depth = VectorR.w / 256.0;\n"
2647 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2648 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2649 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2650 "       gl_FragData1 = depthcolor;\n"
2651 "#else\n"
2652 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2653 "#endif\n"
2654 "}\n"
2655 "#endif // FRAGMENT_SHADER\n"
2656 "#else // !MODE_DEFERREDGEOMETRY\n"
2657 "\n"
2658 "\n"
2659 "\n"
2660 "\n"
2661 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2662 "#ifdef VERTEX_SHADER\n"
2663 "void main\n"
2664 "(\n"
2665 "float4 gl_Vertex : POSITION,\n"
2666 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2667 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2668 "out float4 gl_Position : POSITION,\n"
2669 "out float4 ModelViewPosition : TEXCOORD0\n"
2670 ")\n"
2671 "{\n"
2672 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2673 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2674 "}\n"
2675 "#endif // VERTEX_SHADER\n"
2676 "\n"
2677 "#ifdef FRAGMENT_SHADER\n"
2678 "void main\n"
2679 "(\n"
2680 "#ifdef HLSL\n"
2681 "float2 Pixel : VPOS,\n"
2682 "#else\n"
2683 "float2 Pixel : WPOS,\n"
2684 "#endif\n"
2685 "float4 ModelViewPosition : TEXCOORD0,\n"
2686 "uniform float4x4 ViewToLight : register(c44),\n"
2687 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2688 "uniform float3 LightPosition : register(c23),\n"
2689 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2690 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2691 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2692 "#ifdef USESPECULAR\n"
2693 "uniform half3 DeferredColor_Specular : register(c11),\n"
2694 "uniform half SpecularPower : register(c36),\n"
2695 "#endif\n"
2696 "uniform sampler Texture_Attenuation : register(s9),\n"
2697 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2698 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2699 "\n"
2700 "#ifdef USECUBEFILTER\n"
2701 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2702 "#endif\n"
2703 "\n"
2704 "#ifdef USESHADOWMAP2D\n"
2705 "# ifdef USESHADOWSAMPLER\n"
2706 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2707 "# else\n"
2708 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2709 "# endif\n"
2710 "#endif\n"
2711 "\n"
2712 "#ifdef USESHADOWMAPVSDCT\n"
2713 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2714 "#endif\n"
2715 "\n"
2716 "#if defined(USESHADOWMAP2D)\n"
2717 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2718 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2719 "#endif\n"
2720 "\n"
2721 "out float4 gl_FragData0 : COLOR0,\n"
2722 "out float4 gl_FragData1 : COLOR1\n"
2723 ")\n"
2724 "{\n"
2725 "       // calculate viewspace pixel position\n"
2726 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2727 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2728 "       float3 position;\n"
2729 "#ifdef HLSL\n"
2730 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2731 "#else\n"
2732 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2733 "#endif\n"
2734 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2735 "       // decode viewspace pixel normal\n"
2736 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2737 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2738 "       // surfacenormal = pixel normal in viewspace\n"
2739 "       // LightVector = pixel to light in viewspace\n"
2740 "       // CubeVector = position in lightspace\n"
2741 "       // eyevector = pixel to view in viewspace\n"
2742 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2743 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2744 "#ifdef USEDIFFUSE\n"
2745 "       // calculate diffuse shading\n"
2746 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2747 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2748 "#endif\n"
2749 "#ifdef USESPECULAR\n"
2750 "       // calculate directional shading\n"
2751 "       float3 eyevector = position * -1.0;\n"
2752 "#  ifdef USEEXACTSPECULARMATH\n"
2753 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2754 "#  else\n"
2755 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2756 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2757 "#  endif\n"
2758 "#endif\n"
2759 "\n"
2760 "#if defined(USESHADOWMAP2D)\n"
2761 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2762 "#ifdef USESHADOWMAPVSDCT\n"
2763 ", Texture_CubeProjection\n"
2764 "#endif\n"
2765 "       ));\n"
2766 "#endif\n"
2767 "\n"
2768 "#ifdef USEDIFFUSE\n"
2769 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2770 "#else\n"
2771 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2772 "#endif\n"
2773 "#ifdef USESPECULAR\n"
2774 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2775 "#else\n"
2776 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2777 "#endif\n"
2778 "\n"
2779 "# ifdef USECUBEFILTER\n"
2780 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2781 "       gl_FragData0.rgb *= cubecolor;\n"
2782 "       gl_FragData1.rgb *= cubecolor;\n"
2783 "# endif\n"
2784 "}\n"
2785 "#endif // FRAGMENT_SHADER\n"
2786 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2787 "\n"
2788 "\n"
2789 "\n"
2790 "\n"
2791 "#ifdef VERTEX_SHADER\n"
2792 "void main\n"
2793 "(\n"
2794 "float4 gl_Vertex : POSITION,\n"
2795 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2796 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2797 "float4 gl_Color : COLOR0,\n"
2798 "#endif\n"
2799 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2800 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2801 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2802 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2803 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2804 "\n"
2805 "uniform float3 EyePosition : register(c24),\n"
2806 "uniform float4x4 TexMatrix : register(c0),\n"
2807 "#ifdef USEVERTEXTEXTUREBLEND\n"
2808 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2809 "#endif\n"
2810 "#ifdef MODE_LIGHTSOURCE\n"
2811 "uniform float4x4 ModelToLight : register(c20),\n"
2812 "#endif\n"
2813 "#ifdef MODE_LIGHTSOURCE\n"
2814 "uniform float3 LightPosition : register(c27),\n"
2815 "#endif\n"
2816 "#ifdef MODE_LIGHTDIRECTION\n"
2817 "uniform float3 LightDir : register(c26),\n"
2818 "#endif\n"
2819 "uniform float4 FogPlane : register(c25),\n"
2820 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2821 "uniform float3 LightPosition : register(c27),\n"
2822 "#endif\n"
2823 "#ifdef USESHADOWMAPORTHO\n"
2824 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2825 "#endif\n"
2826 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2827 "out float4 gl_FrontColor : COLOR,\n"
2828 "#endif\n"
2829 "out float4 TexCoordBoth : TEXCOORD0,\n"
2830 "#ifdef USELIGHTMAP\n"
2831 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2832 "#endif\n"
2833 "#ifdef USEEYEVECTOR\n"
2834 "out float3 EyeVector : TEXCOORD2,\n"
2835 "#endif\n"
2836 "#ifdef USEREFLECTION\n"
2837 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2838 "#endif\n"
2839 "#ifdef USEFOG\n"
2840 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2841 "#endif\n"
2842 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2843 "out float3 LightVector : TEXCOORD1,\n"
2844 "#endif\n"
2845 "#ifdef MODE_LIGHTSOURCE\n"
2846 "out float3 CubeVector : TEXCOORD3,\n"
2847 "#endif\n"
2848 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2849 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2850 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2851 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2852 "#endif\n"
2853 "#ifdef USESHADOWMAPORTHO\n"
2854 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2855 "#endif\n"
2856 "out float4 gl_Position : POSITION\n"
2857 ")\n"
2858 "{\n"
2859 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2860 "#ifdef HLSL\n"
2861 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2862 "#else\n"
2863 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2864 "#endif\n"
2865 "#endif\n"
2866 "       // copy the surface texcoord\n"
2867 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2868 "#ifdef USEVERTEXTEXTUREBLEND\n"
2869 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2870 "#endif\n"
2871 "#ifdef USELIGHTMAP\n"
2872 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2873 "#endif\n"
2874 "\n"
2875 "#ifdef MODE_LIGHTSOURCE\n"
2876 "       // transform vertex position into light attenuation/cubemap space\n"
2877 "       // (-1 to +1 across the light box)\n"
2878 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2879 "\n"
2880 "# ifdef USEDIFFUSE\n"
2881 "       // transform unnormalized light direction into tangent space\n"
2882 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2883 "       //  normalize it per pixel)\n"
2884 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2885 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2886 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2887 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2888 "# endif\n"
2889 "#endif\n"
2890 "\n"
2891 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2892 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2893 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2894 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2895 "#endif\n"
2896 "\n"
2897 "       // transform unnormalized eye direction into tangent space\n"
2898 "#ifdef USEEYEVECTOR\n"
2899 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2900 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2901 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2902 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2903 "#endif\n"
2904 "\n"
2905 "#ifdef USEFOG\n"
2906 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2907 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2908 "#endif\n"
2909 "\n"
2910 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2911 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2912 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2913 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2914 "#endif\n"
2915 "\n"
2916 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2917 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2918 "\n"
2919 "#ifdef USESHADOWMAPORTHO\n"
2920 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2921 "#endif\n"
2922 "\n"
2923 "#ifdef USEREFLECTION\n"
2924 "       ModelViewProjectionPosition = gl_Position;\n"
2925 "#endif\n"
2926 "}\n"
2927 "#endif // VERTEX_SHADER\n"
2928 "\n"
2929 "\n"
2930 "\n"
2931 "\n"
2932 "#ifdef FRAGMENT_SHADER\n"
2933 "void main\n"
2934 "(\n"
2935 "#ifdef USEDEFERREDLIGHTMAP\n"
2936 "#ifdef HLSL\n"
2937 "float2 Pixel : VPOS,\n"
2938 "#else\n"
2939 "float2 Pixel : WPOS,\n"
2940 "#endif\n"
2941 "#endif\n"
2942 "float4 gl_FrontColor : COLOR,\n"
2943 "float4 TexCoordBoth : TEXCOORD0,\n"
2944 "#ifdef USELIGHTMAP\n"
2945 "float2 TexCoordLightmap : TEXCOORD1,\n"
2946 "#endif\n"
2947 "#ifdef USEEYEVECTOR\n"
2948 "float3 EyeVector : TEXCOORD2,\n"
2949 "#endif\n"
2950 "#ifdef USEREFLECTION\n"
2951 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2952 "#endif\n"
2953 "#ifdef USEFOG\n"
2954 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2955 "#endif\n"
2956 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2957 "float3 LightVector : TEXCOORD1,\n"
2958 "#endif\n"
2959 "#ifdef MODE_LIGHTSOURCE\n"
2960 "float3 CubeVector : TEXCOORD3,\n"
2961 "#endif\n"
2962 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2963 "float4 ModelViewPosition : TEXCOORD0,\n"
2964 "#endif\n"
2965 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2966 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2967 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2968 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2969 "#endif\n"
2970 "#ifdef USESHADOWMAPORTHO\n"
2971 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2972 "#endif\n"
2973 "\n"
2974 "uniform sampler Texture_Normal : register(s0),\n"
2975 "uniform sampler Texture_Color : register(s1),\n"
2976 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2977 "uniform sampler Texture_Gloss : register(s2),\n"
2978 "#endif\n"
2979 "#ifdef USEGLOW\n"
2980 "uniform sampler Texture_Glow : register(s3),\n"
2981 "#endif\n"
2982 "#ifdef USEVERTEXTEXTUREBLEND\n"
2983 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2984 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2985 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2986 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2987 "#endif\n"
2988 "#ifdef USEGLOW\n"
2989 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2990 "#endif\n"
2991 "#endif\n"
2992 "#ifdef USECOLORMAPPING\n"
2993 "uniform sampler Texture_Pants : register(s4),\n"
2994 "uniform sampler Texture_Shirt : register(s7),\n"
2995 "#endif\n"
2996 "#ifdef USEFOG\n"
2997 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2998 "uniform sampler Texture_FogMask : register(s8),\n"
2999 "#endif\n"
3000 "#ifdef USELIGHTMAP\n"
3001 "uniform sampler Texture_Lightmap : register(s9),\n"
3002 "#endif\n"
3003 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3004 "uniform sampler Texture_Deluxemap : register(s10),\n"
3005 "#endif\n"
3006 "#ifdef USEREFLECTION\n"
3007 "uniform sampler Texture_Reflection : register(s7),\n"
3008 "#endif\n"
3009 "\n"
3010 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3011 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3012 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3013 "#endif\n"
3014 "#ifdef USEDEFERREDLIGHTMAP\n"
3015 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3016 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3017 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3018 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3019 "#endif\n"
3020 "\n"
3021 "#ifdef USECOLORMAPPING\n"
3022 "uniform half3 Color_Pants : register(c7),\n"
3023 "uniform half3 Color_Shirt : register(c8),\n"
3024 "#endif\n"
3025 "#ifdef USEFOG\n"
3026 "uniform float3 FogColor : register(c16),\n"
3027 "uniform float FogRangeRecip : register(c20),\n"
3028 "uniform float FogPlaneViewDist : register(c19),\n"
3029 "uniform float FogHeightFade : register(c17),\n"
3030 "#endif\n"
3031 "\n"
3032 "#ifdef USEOFFSETMAPPING\n"
3033 "uniform float OffsetMapping_Scale : register(c24),\n"
3034 "#endif\n"
3035 "\n"
3036 "#ifdef USEDEFERREDLIGHTMAP\n"
3037 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3038 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3039 "uniform half3 DeferredMod_Specular : register(c13),\n"
3040 "#endif\n"
3041 "uniform half3 Color_Ambient : register(c3),\n"
3042 "uniform half3 Color_Diffuse : register(c4),\n"
3043 "uniform half3 Color_Specular : register(c5),\n"
3044 "uniform half SpecularPower : register(c36),\n"
3045 "#ifdef USEGLOW\n"
3046 "uniform half3 Color_Glow : register(c6),\n"
3047 "#endif\n"
3048 "uniform half Alpha : register(c0),\n"
3049 "#ifdef USEREFLECTION\n"
3050 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3051 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3052 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3053 "uniform half4 ReflectColor : register(c26),\n"
3054 "#endif\n"
3055 "#ifdef USEREFLECTCUBE\n"
3056 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3057 "uniform sampler Texture_ReflectMask : register(s5),\n"
3058 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3059 "#endif\n"
3060 "#ifdef MODE_LIGHTDIRECTION\n"
3061 "uniform half3 LightColor : register(c21),\n"
3062 "#endif\n"
3063 "#ifdef MODE_LIGHTSOURCE\n"
3064 "uniform half3 LightColor : register(c21),\n"
3065 "#endif\n"
3066 "\n"
3067 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3068 "uniform sampler Texture_Attenuation : register(s9),\n"
3069 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3070 "#endif\n"
3071 "\n"
3072 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3073 "\n"
3074 "#ifdef USESHADOWMAP2D\n"
3075 "# ifdef USESHADOWSAMPLER\n"
3076 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3077 "# else\n"
3078 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3079 "# endif\n"
3080 "#endif\n"
3081 "\n"
3082 "#ifdef USESHADOWMAPVSDCT\n"
3083 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3084 "#endif\n"
3085 "\n"
3086 "#if defined(USESHADOWMAP2D)\n"
3087 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3088 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3089 "#endif\n"
3090 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3091 "\n"
3092 "out float4 gl_FragColor : COLOR\n"
3093 ")\n"
3094 "{\n"
3095 "       float2 TexCoord = TexCoordBoth.xy;\n"
3096 "#ifdef USEVERTEXTEXTUREBLEND\n"
3097 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3098 "#endif\n"
3099 "#ifdef USEOFFSETMAPPING\n"
3100 "       // apply offsetmapping\n"
3101 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3102 "#define TexCoord TexCoordOffset\n"
3103 "#endif\n"
3104 "\n"
3105 "       // combine the diffuse textures (base, pants, shirt)\n"
3106 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3107 "#ifdef USEALPHAKILL\n"
3108 "       if (color.a < 0.5)\n"
3109 "               discard;\n"
3110 "#endif\n"
3111 "       color.a *= Alpha;\n"
3112 "#ifdef USECOLORMAPPING\n"
3113 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3114 "#endif\n"
3115 "#ifdef USEVERTEXTEXTUREBLEND\n"
3116 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3117 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3118 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3119 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3120 "       color.a = 1.0;\n"
3121 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3122 "#endif\n"
3123 "\n"
3124 "       // get the surface normal\n"
3125 "#ifdef USEVERTEXTEXTUREBLEND\n"
3126 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3127 "#else\n"
3128 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3129 "#endif\n"
3130 "\n"
3131 "       // get the material colors\n"
3132 "       half3 diffusetex = color.rgb;\n"
3133 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3134 "# ifdef USEVERTEXTEXTUREBLEND\n"
3135 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3136 "# else\n"
3137 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3138 "# endif\n"
3139 "#endif\n"
3140 "\n"
3141 "#ifdef USEREFLECTCUBE\n"
3142 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3143 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3144 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3145 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3146 "#endif\n"
3147 "\n"
3148 "\n"
3149 "\n"
3150 "\n"
3151 "#ifdef MODE_LIGHTSOURCE\n"
3152 "       // light source\n"
3153 "#ifdef USEDIFFUSE\n"
3154 "       half3 lightnormal = half3(normalize(LightVector));\n"
3155 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3156 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3157 "#ifdef USESPECULAR\n"
3158 "#ifdef USEEXACTSPECULARMATH\n"
3159 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3160 "#else\n"
3161 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3162 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3163 "#endif\n"
3164 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3165 "#endif\n"
3166 "#else\n"
3167 "       color.rgb = diffusetex * Color_Ambient;\n"
3168 "#endif\n"
3169 "       color.rgb *= LightColor;\n"
3170 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3171 "#if defined(USESHADOWMAP2D)\n"
3172 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3173 "#ifdef USESHADOWMAPVSDCT\n"
3174 ", Texture_CubeProjection\n"
3175 "#endif\n"
3176 "       ));\n"
3177 "\n"
3178 "#endif\n"
3179 "# ifdef USECUBEFILTER\n"
3180 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3181 "# endif\n"
3182 "\n"
3183 "#ifdef USESHADOWMAP2D\n"
3184 "#ifdef USESHADOWMAPVSDCT\n"
3185 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3186 "#else\n"
3187 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3188 "#endif\n"
3189 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3190 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3191 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3192 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3193 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3194 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3195 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3196 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3197 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3198 "//     color.r = half(shadowmaptc.z);\n"
3199 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3200 "//     color.r = half(shadowmaptc.z);\n"
3201 "//     color.r = 1;\n"
3202 "//     color.rgb = abs(CubeVector);\n"
3203 "#endif\n"
3204 "//     color.rgb = half3(1,1,1);\n"
3205 "#endif // MODE_LIGHTSOURCE\n"
3206 "\n"
3207 "\n"
3208 "\n"
3209 "\n"
3210 "#ifdef MODE_LIGHTDIRECTION\n"
3211 "#define SHADING\n"
3212 "#ifdef USEDIFFUSE\n"
3213 "       half3 lightnormal = half3(normalize(LightVector));\n"
3214 "#endif\n"
3215 "#define lightcolor LightColor\n"
3216 "#endif // MODE_LIGHTDIRECTION\n"
3217 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3218 "#define SHADING\n"
3219 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3220 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3221 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3222 "       // convert modelspace light vector to tangentspace\n"
3223 "       half3 lightnormal;\n"
3224 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3225 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3226 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3227 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3228 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3229 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3230 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3231 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3232 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3233 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3234 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3235 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3236 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3237 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3238 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3239 "#define SHADING\n"
3240 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3241 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3242 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3243 "#endif\n"
3244 "\n"
3245 "\n"
3246 "\n"
3247 "\n"
3248 "#ifdef MODE_FAKELIGHT\n"
3249 "#define SHADING\n"
3250 "half3 lightnormal = half3(normalize(EyeVector));\n"
3251 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3252 "#endif // MODE_FAKELIGHT\n"
3253 "\n"
3254 "\n"
3255 "\n"
3256 "\n"
3257 "#ifdef MODE_LIGHTMAP\n"
3258 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3259 "#endif // MODE_LIGHTMAP\n"
3260 "#ifdef MODE_VERTEXCOLOR\n"
3261 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3262 "#endif // MODE_VERTEXCOLOR\n"
3263 "#ifdef MODE_FLATCOLOR\n"
3264 "       color.rgb = diffusetex * Color_Ambient;\n"
3265 "#endif // MODE_FLATCOLOR\n"
3266 "\n"
3267 "\n"
3268 "\n"
3269 "\n"
3270 "#ifdef SHADING\n"
3271 "# ifdef USEDIFFUSE\n"
3272 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3273 "#  ifdef USESPECULAR\n"
3274 "#   ifdef USEEXACTSPECULARMATH\n"
3275 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3276 "#   else\n"
3277 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3278 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3279 "#   endif\n"
3280 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3281 "#  else\n"
3282 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3283 "#  endif\n"
3284 "# else\n"
3285 "       color.rgb = diffusetex * Color_Ambient;\n"
3286 "# endif\n"
3287 "#endif\n"
3288 "\n"
3289 "#ifdef USESHADOWMAPORTHO\n"
3290 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3291 "#endif\n"
3292 "\n"
3293 "#ifdef USEDEFERREDLIGHTMAP\n"
3294 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3295 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3296 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3297 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3298 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3299 "#endif\n"
3300 "\n"
3301 "#ifdef USEGLOW\n"
3302 "#ifdef USEVERTEXTEXTUREBLEND\n"
3303 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3304 "#else\n"
3305 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3306 "#endif\n"
3307 "#endif\n"
3308 "\n"
3309 "#ifdef USEFOG\n"
3310 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3311 "#endif\n"
3312 "\n"
3313 "       // 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"
3314 "#ifdef USEREFLECTION\n"
3315 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3316 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3317 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3318 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3319 "       // FIXME temporary hack to detect the case that the reflection\n"
3320 "       // gets blackened at edges due to leaving the area that contains actual\n"
3321 "       // content.\n"
3322 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3323 "       // 'appening.\n"
3324 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3325 "       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 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3329 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3330 "#endif\n"
3331 "\n"
3332 "       gl_FragColor = float4(color);\n"
3333 "}\n"
3334 "#endif // FRAGMENT_SHADER\n"
3335 "\n"
3336 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3337 "#endif // !MODE_DEFERREDGEOMETRY\n"
3338 "#endif // !MODE_WATER\n"
3339 "#endif // !MODE_REFRACTION\n"
3340 "#endif // !MODE_BLOOMBLUR\n"
3341 "#endif // !MODE_GENERIC\n"
3342 "#endif // !MODE_POSTPROCESS\n"
3343 "#endif // !MODE_SHOWDEPTH\n"
3344 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3345 ;
3346
3347 char *glslshaderstring = NULL;
3348 char *hlslshaderstring = NULL;
3349
3350 //=======================================================================================================================================================
3351
3352 typedef struct shaderpermutationinfo_s
3353 {
3354         const char *pretext;
3355         const char *name;
3356 }
3357 shaderpermutationinfo_t;
3358
3359 typedef struct shadermodeinfo_s
3360 {
3361         const char *vertexfilename;
3362         const char *geometryfilename;
3363         const char *fragmentfilename;
3364         const char *pretext;
3365         const char *name;
3366 }
3367 shadermodeinfo_t;
3368
3369 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3370 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3371 {
3372         {"#define USEDIFFUSE\n", " diffuse"},
3373         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3374         {"#define USEVIEWTINT\n", " viewtint"},
3375         {"#define USECOLORMAPPING\n", " colormapping"},
3376         {"#define USESATURATION\n", " saturation"},
3377         {"#define USEFOGINSIDE\n", " foginside"},
3378         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3379         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3380         {"#define USEGAMMARAMPS\n", " gammaramps"},
3381         {"#define USECUBEFILTER\n", " cubefilter"},
3382         {"#define USEGLOW\n", " glow"},
3383         {"#define USEBLOOM\n", " bloom"},
3384         {"#define USESPECULAR\n", " specular"},
3385         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3386         {"#define USEREFLECTION\n", " reflection"},
3387         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3388         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3389         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3390         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3391         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3392         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3393         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3394         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3395         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3396         {"#define USEALPHAKILL\n", " alphakill"},
3397         {"#define USEREFLECTCUBE\n", " reflectcube"},
3398         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3399 };
3400
3401 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3402 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3403 {
3404         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3405         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3406         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3407         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3408         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3409         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3410         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3411         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3412         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3413         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3414         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3415         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3416         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3417         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3418         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3419         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3420 };
3421
3422 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3423 {
3424         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3425         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3426         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3427         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3428         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3429         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3430         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3431         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3432         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3433         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3434         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3435         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3436         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3437         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3438         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3439         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3440 };
3441
3442 struct r_glsl_permutation_s;
3443 typedef struct r_glsl_permutation_s
3444 {
3445         /// hash lookup data
3446         struct r_glsl_permutation_s *hashnext;
3447         unsigned int mode;
3448         unsigned int permutation;
3449
3450         /// indicates if we have tried compiling this permutation already
3451         qboolean compiled;
3452         /// 0 if compilation failed
3453         int program;
3454         // texture units assigned to each detected uniform
3455         int tex_Texture_First;
3456         int tex_Texture_Second;
3457         int tex_Texture_GammaRamps;
3458         int tex_Texture_Normal;
3459         int tex_Texture_Color;
3460         int tex_Texture_Gloss;
3461         int tex_Texture_Glow;
3462         int tex_Texture_SecondaryNormal;
3463         int tex_Texture_SecondaryColor;
3464         int tex_Texture_SecondaryGloss;
3465         int tex_Texture_SecondaryGlow;
3466         int tex_Texture_Pants;
3467         int tex_Texture_Shirt;
3468         int tex_Texture_FogHeightTexture;
3469         int tex_Texture_FogMask;
3470         int tex_Texture_Lightmap;
3471         int tex_Texture_Deluxemap;
3472         int tex_Texture_Attenuation;
3473         int tex_Texture_Cube;
3474         int tex_Texture_Refraction;
3475         int tex_Texture_Reflection;
3476         int tex_Texture_ShadowMap2D;
3477         int tex_Texture_CubeProjection;
3478         int tex_Texture_ScreenDepth;
3479         int tex_Texture_ScreenNormalMap;
3480         int tex_Texture_ScreenDiffuse;
3481         int tex_Texture_ScreenSpecular;
3482         int tex_Texture_ReflectMask;
3483         int tex_Texture_ReflectCube;
3484         /// locations of detected uniforms in program object, or -1 if not found
3485         int loc_Texture_First;
3486         int loc_Texture_Second;
3487         int loc_Texture_GammaRamps;
3488         int loc_Texture_Normal;
3489         int loc_Texture_Color;
3490         int loc_Texture_Gloss;
3491         int loc_Texture_Glow;
3492         int loc_Texture_SecondaryNormal;
3493         int loc_Texture_SecondaryColor;
3494         int loc_Texture_SecondaryGloss;
3495         int loc_Texture_SecondaryGlow;
3496         int loc_Texture_Pants;
3497         int loc_Texture_Shirt;
3498         int loc_Texture_FogHeightTexture;
3499         int loc_Texture_FogMask;
3500         int loc_Texture_Lightmap;
3501         int loc_Texture_Deluxemap;
3502         int loc_Texture_Attenuation;
3503         int loc_Texture_Cube;
3504         int loc_Texture_Refraction;
3505         int loc_Texture_Reflection;
3506         int loc_Texture_ShadowMap2D;
3507         int loc_Texture_CubeProjection;
3508         int loc_Texture_ScreenDepth;
3509         int loc_Texture_ScreenNormalMap;
3510         int loc_Texture_ScreenDiffuse;
3511         int loc_Texture_ScreenSpecular;
3512         int loc_Texture_ReflectMask;
3513         int loc_Texture_ReflectCube;
3514         int loc_Alpha;
3515         int loc_BloomBlur_Parameters;
3516         int loc_ClientTime;
3517         int loc_Color_Ambient;
3518         int loc_Color_Diffuse;
3519         int loc_Color_Specular;
3520         int loc_Color_Glow;
3521         int loc_Color_Pants;
3522         int loc_Color_Shirt;
3523         int loc_DeferredColor_Ambient;
3524         int loc_DeferredColor_Diffuse;
3525         int loc_DeferredColor_Specular;
3526         int loc_DeferredMod_Diffuse;
3527         int loc_DeferredMod_Specular;
3528         int loc_DistortScaleRefractReflect;
3529         int loc_EyePosition;
3530         int loc_FogColor;
3531         int loc_FogHeightFade;
3532         int loc_FogPlane;
3533         int loc_FogPlaneViewDist;
3534         int loc_FogRangeRecip;
3535         int loc_LightColor;
3536         int loc_LightDir;
3537         int loc_LightPosition;
3538         int loc_OffsetMapping_Scale;
3539         int loc_PixelSize;
3540         int loc_ReflectColor;
3541         int loc_ReflectFactor;
3542         int loc_ReflectOffset;
3543         int loc_RefractColor;
3544         int loc_Saturation;
3545         int loc_ScreenCenterRefractReflect;
3546         int loc_ScreenScaleRefractReflect;
3547         int loc_ScreenToDepth;
3548         int loc_ShadowMap_Parameters;
3549         int loc_ShadowMap_TextureScale;
3550         int loc_SpecularPower;
3551         int loc_UserVec1;
3552         int loc_UserVec2;
3553         int loc_UserVec3;
3554         int loc_UserVec4;
3555         int loc_ViewTintColor;
3556         int loc_ViewToLight;
3557         int loc_ModelToLight;
3558         int loc_TexMatrix;
3559         int loc_BackgroundTexMatrix;
3560         int loc_ModelViewProjectionMatrix;
3561         int loc_ModelViewMatrix;
3562         int loc_PixelToScreenTexCoord;
3563         int loc_ModelToReflectCube;
3564         int loc_ShadowMapMatrix;
3565         int loc_BloomColorSubtract;
3566         int loc_NormalmapScrollBlend;
3567 }
3568 r_glsl_permutation_t;
3569
3570 #define SHADERPERMUTATION_HASHSIZE 256
3571
3572
3573 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3574 // these can NOT degrade! only use for simple stuff
3575 enum
3576 {
3577         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3578         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3579         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3580         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3581         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3582         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3583 };
3584 #define SHADERSTATICPARMS_COUNT 6
3585
3586 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3587 static int shaderstaticparms_count = 0;
3588
3589 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3590 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3591 qboolean R_CompileShader_CheckStaticParms(void)
3592 {
3593         static int r_compileshader_staticparms_save[1];
3594         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3595         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3596
3597         // detect all
3598         if (r_glsl_saturation_redcompensate.integer)
3599                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3600         if (r_shadow_glossexact.integer)
3601                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3602         if (r_glsl_postprocess.integer)
3603         {
3604                 if (r_glsl_postprocess_uservec1_enable.integer)
3605                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3606                 if (r_glsl_postprocess_uservec2_enable.integer)
3607                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3608                 if (r_glsl_postprocess_uservec3_enable.integer)
3609                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3610                 if (r_glsl_postprocess_uservec4_enable.integer)
3611                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3612         }
3613         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3614 }
3615
3616 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3617         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3618                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3619         else \
3620                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3621 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3622 {
3623         shaderstaticparms_count = 0;
3624
3625         // emit all
3626         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3627         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3628         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3629         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3630         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3631         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3632 }
3633
3634 /// information about each possible shader permutation
3635 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3636 /// currently selected permutation
3637 r_glsl_permutation_t *r_glsl_permutation;
3638 /// storage for permutations linked in the hash table
3639 memexpandablearray_t r_glsl_permutationarray;
3640
3641 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3642 {
3643         //unsigned int hashdepth = 0;
3644         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3645         r_glsl_permutation_t *p;
3646         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3647         {
3648                 if (p->mode == mode && p->permutation == permutation)
3649                 {
3650                         //if (hashdepth > 10)
3651                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3652                         return p;
3653                 }
3654                 //hashdepth++;
3655         }
3656         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3657         p->mode = mode;
3658         p->permutation = permutation;
3659         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3660         r_glsl_permutationhash[mode][hashindex] = p;
3661         //if (hashdepth > 10)
3662         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3663         return p;
3664 }
3665
3666 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3667 {
3668         char *shaderstring;
3669         if (!filename || !filename[0])
3670                 return NULL;
3671         if (!strcmp(filename, "glsl/default.glsl"))
3672         {
3673                 if (!glslshaderstring)
3674                 {
3675                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3676                         if (glslshaderstring)
3677                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3678                         else
3679                                 glslshaderstring = (char *)builtinshaderstring;
3680                 }
3681                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3682                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3683                 return shaderstring;
3684         }
3685         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3686         if (shaderstring)
3687         {
3688                 if (printfromdisknotice)
3689                         Con_DPrintf("from disk %s... ", filename);
3690                 return shaderstring;
3691         }
3692         return shaderstring;
3693 }
3694
3695 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3696 {
3697         int i;
3698         int sampler;
3699         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3700         char *vertexstring, *geometrystring, *fragmentstring;
3701         char permutationname[256];
3702         int vertstrings_count = 0;
3703         int geomstrings_count = 0;
3704         int fragstrings_count = 0;
3705         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3706         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3707         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3708
3709         if (p->compiled)
3710                 return;
3711         p->compiled = true;
3712         p->program = 0;
3713
3714         permutationname[0] = 0;
3715         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3716         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3717         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3718
3719         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3720
3721         // the first pretext is which type of shader to compile as
3722         // (later these will all be bound together as a program object)
3723         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3724         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3725         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3726
3727         // the second pretext is the mode (for example a light source)
3728         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3729         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3730         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3731         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3732
3733         // now add all the permutation pretexts
3734         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3735         {
3736                 if (permutation & (1<<i))
3737                 {
3738                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3739                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3740                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3741                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3742                 }
3743                 else
3744                 {
3745                         // keep line numbers correct
3746                         vertstrings_list[vertstrings_count++] = "\n";
3747                         geomstrings_list[geomstrings_count++] = "\n";
3748                         fragstrings_list[fragstrings_count++] = "\n";
3749                 }
3750         }
3751
3752         // add static parms
3753         R_CompileShader_AddStaticParms(mode, permutation);
3754         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3755         vertstrings_count += shaderstaticparms_count;
3756         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3757         geomstrings_count += shaderstaticparms_count;
3758         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3759         fragstrings_count += shaderstaticparms_count;
3760
3761         // now append the shader text itself
3762         vertstrings_list[vertstrings_count++] = vertexstring;
3763         geomstrings_list[geomstrings_count++] = geometrystring;
3764         fragstrings_list[fragstrings_count++] = fragmentstring;
3765
3766         // if any sources were NULL, clear the respective list
3767         if (!vertexstring)
3768                 vertstrings_count = 0;
3769         if (!geometrystring)
3770                 geomstrings_count = 0;
3771         if (!fragmentstring)
3772                 fragstrings_count = 0;
3773
3774         // compile the shader program
3775         if (vertstrings_count + geomstrings_count + fragstrings_count)
3776                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3777         if (p->program)
3778         {
3779                 CHECKGLERROR
3780                 qglUseProgram(p->program);CHECKGLERROR
3781                 // look up all the uniform variable names we care about, so we don't
3782                 // have to look them up every time we set them
3783
3784                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
3785                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
3786                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3787                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
3788                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
3789                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
3790                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
3791                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3792                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3793                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3794                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3795                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
3796                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
3797                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3798                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
3799                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
3800                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3801                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
3802                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
3803                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
3804                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
3805                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3806                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3807                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3808                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3809                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3810                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3811                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3812                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3813                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
3814                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3815                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
3816                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
3817                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
3818                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
3819                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
3820                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
3821                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
3822                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3823                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3824                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3825                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3826                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3827                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3828                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
3829                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
3830                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
3831                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
3832                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3833                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
3834                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
3835                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
3836                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
3837                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3838                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
3839                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
3840                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
3841                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
3842                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
3843                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
3844                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3845                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3846                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
3847                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3848                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3849                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
3850                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
3851                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
3852                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
3853                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
3854                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
3855                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
3856                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
3857                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
3858                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3859                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
3860                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3861                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3862                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
3863                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3864                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
3865                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3866                 // initialize the samplers to refer to the texture units we use
3867                 p->tex_Texture_First = -1;
3868                 p->tex_Texture_Second = -1;
3869                 p->tex_Texture_GammaRamps = -1;
3870                 p->tex_Texture_Normal = -1;
3871                 p->tex_Texture_Color = -1;
3872                 p->tex_Texture_Gloss = -1;
3873                 p->tex_Texture_Glow = -1;
3874                 p->tex_Texture_SecondaryNormal = -1;
3875                 p->tex_Texture_SecondaryColor = -1;
3876                 p->tex_Texture_SecondaryGloss = -1;
3877                 p->tex_Texture_SecondaryGlow = -1;
3878                 p->tex_Texture_Pants = -1;
3879                 p->tex_Texture_Shirt = -1;
3880                 p->tex_Texture_FogHeightTexture = -1;
3881                 p->tex_Texture_FogMask = -1;
3882                 p->tex_Texture_Lightmap = -1;
3883                 p->tex_Texture_Deluxemap = -1;
3884                 p->tex_Texture_Attenuation = -1;
3885                 p->tex_Texture_Cube = -1;
3886                 p->tex_Texture_Refraction = -1;
3887                 p->tex_Texture_Reflection = -1;
3888                 p->tex_Texture_ShadowMap2D = -1;
3889                 p->tex_Texture_CubeProjection = -1;
3890                 p->tex_Texture_ScreenDepth = -1;
3891                 p->tex_Texture_ScreenNormalMap = -1;
3892                 p->tex_Texture_ScreenDiffuse = -1;
3893                 p->tex_Texture_ScreenSpecular = -1;
3894                 p->tex_Texture_ReflectMask = -1;
3895                 p->tex_Texture_ReflectCube = -1;
3896                 sampler = 0;
3897                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
3898                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
3899                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
3900                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
3901                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
3902                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
3903                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
3904                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3905                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
3906                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
3907                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
3908                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
3909                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
3910                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3911                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
3912                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
3913                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
3914                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
3915                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
3916                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
3917                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
3918                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
3919                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
3920                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
3921                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3922                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
3923                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
3924                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
3925                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
3926                 CHECKGLERROR
3927                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3928         }
3929         else
3930                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3931
3932         // free the strings
3933         if (vertexstring)
3934                 Mem_Free(vertexstring);
3935         if (geometrystring)
3936                 Mem_Free(geometrystring);
3937         if (fragmentstring)
3938                 Mem_Free(fragmentstring);
3939 }
3940
3941 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3942 {
3943         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3944         if (r_glsl_permutation != perm)
3945         {
3946                 r_glsl_permutation = perm;
3947                 if (!r_glsl_permutation->program)
3948                 {
3949                         if (!r_glsl_permutation->compiled)
3950                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3951                         if (!r_glsl_permutation->program)
3952                         {
3953                                 // remove features until we find a valid permutation
3954                                 int i;
3955                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3956                                 {
3957                                         // reduce i more quickly whenever it would not remove any bits
3958                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3959                                         if (!(permutation & j))
3960                                                 continue;
3961                                         permutation -= j;
3962                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3963                                         if (!r_glsl_permutation->compiled)
3964                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3965                                         if (r_glsl_permutation->program)
3966                                                 break;
3967                                 }
3968                                 if (i >= SHADERPERMUTATION_COUNT)
3969                                 {
3970                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3971                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3972                                         qglUseProgram(0);CHECKGLERROR
3973                                         return; // no bit left to clear, entire mode is broken
3974                                 }
3975                         }
3976                 }
3977                 CHECKGLERROR
3978                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
3979         }
3980         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3981         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3982         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
3983 }
3984
3985 #ifdef SUPPORTD3D
3986
3987 #ifdef SUPPORTD3D
3988 #include <d3d9.h>
3989 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
3990 extern D3DCAPS9 vid_d3d9caps;
3991 #endif
3992
3993 struct r_hlsl_permutation_s;
3994 typedef struct r_hlsl_permutation_s
3995 {
3996         /// hash lookup data
3997         struct r_hlsl_permutation_s *hashnext;
3998         unsigned int mode;
3999         unsigned int permutation;
4000
4001         /// indicates if we have tried compiling this permutation already
4002         qboolean compiled;
4003         /// NULL if compilation failed
4004         IDirect3DVertexShader9 *vertexshader;
4005         IDirect3DPixelShader9 *pixelshader;
4006 }
4007 r_hlsl_permutation_t;
4008
4009 typedef enum D3DVSREGISTER_e
4010 {
4011         D3DVSREGISTER_TexMatrix = 0, // float4x4
4012         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4013         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4014         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4015         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4016         D3DVSREGISTER_ModelToLight = 20, // float4x4
4017         D3DVSREGISTER_EyePosition = 24,
4018         D3DVSREGISTER_FogPlane = 25,
4019         D3DVSREGISTER_LightDir = 26,
4020         D3DVSREGISTER_LightPosition = 27,
4021 }
4022 D3DVSREGISTER_t;
4023
4024 typedef enum D3DPSREGISTER_e
4025 {
4026         D3DPSREGISTER_Alpha = 0,
4027         D3DPSREGISTER_BloomBlur_Parameters = 1,
4028         D3DPSREGISTER_ClientTime = 2,
4029         D3DPSREGISTER_Color_Ambient = 3,
4030         D3DPSREGISTER_Color_Diffuse = 4,
4031         D3DPSREGISTER_Color_Specular = 5,
4032         D3DPSREGISTER_Color_Glow = 6,
4033         D3DPSREGISTER_Color_Pants = 7,
4034         D3DPSREGISTER_Color_Shirt = 8,
4035         D3DPSREGISTER_DeferredColor_Ambient = 9,
4036         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4037         D3DPSREGISTER_DeferredColor_Specular = 11,
4038         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4039         D3DPSREGISTER_DeferredMod_Specular = 13,
4040         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4041         D3DPSREGISTER_EyePosition = 15, // unused
4042         D3DPSREGISTER_FogColor = 16,
4043         D3DPSREGISTER_FogHeightFade = 17,
4044         D3DPSREGISTER_FogPlane = 18,
4045         D3DPSREGISTER_FogPlaneViewDist = 19,
4046         D3DPSREGISTER_FogRangeRecip = 20,
4047         D3DPSREGISTER_LightColor = 21,
4048         D3DPSREGISTER_LightDir = 22, // unused
4049         D3DPSREGISTER_LightPosition = 23,
4050         D3DPSREGISTER_OffsetMapping_Scale = 24,
4051         D3DPSREGISTER_PixelSize = 25,
4052         D3DPSREGISTER_ReflectColor = 26,
4053         D3DPSREGISTER_ReflectFactor = 27,
4054         D3DPSREGISTER_ReflectOffset = 28,
4055         D3DPSREGISTER_RefractColor = 29,
4056         D3DPSREGISTER_Saturation = 30,
4057         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4058         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4059         D3DPSREGISTER_ScreenToDepth = 33,
4060         D3DPSREGISTER_ShadowMap_Parameters = 34,
4061         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4062         D3DPSREGISTER_SpecularPower = 36,
4063         D3DPSREGISTER_UserVec1 = 37,
4064         D3DPSREGISTER_UserVec2 = 38,
4065         D3DPSREGISTER_UserVec3 = 39,
4066         D3DPSREGISTER_UserVec4 = 40,
4067         D3DPSREGISTER_ViewTintColor = 41,
4068         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4069         D3DPSREGISTER_BloomColorSubtract = 43,
4070         D3DPSREGISTER_ViewToLight = 44, // float4x4
4071         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4072         D3DPSREGISTER_NormalmapScrollBlend = 52,
4073         // next at 53
4074 }
4075 D3DPSREGISTER_t;
4076
4077 /// information about each possible shader permutation
4078 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4079 /// currently selected permutation
4080 r_hlsl_permutation_t *r_hlsl_permutation;
4081 /// storage for permutations linked in the hash table
4082 memexpandablearray_t r_hlsl_permutationarray;
4083
4084 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4085 {
4086         //unsigned int hashdepth = 0;
4087         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4088         r_hlsl_permutation_t *p;
4089         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4090         {
4091                 if (p->mode == mode && p->permutation == permutation)
4092                 {
4093                         //if (hashdepth > 10)
4094                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4095                         return p;
4096                 }
4097                 //hashdepth++;
4098         }
4099         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4100         p->mode = mode;
4101         p->permutation = permutation;
4102         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4103         r_hlsl_permutationhash[mode][hashindex] = p;
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
4109 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4110 {
4111         char *shaderstring;
4112         if (!filename || !filename[0])
4113                 return NULL;
4114         if (!strcmp(filename, "hlsl/default.hlsl"))
4115         {
4116                 if (!hlslshaderstring)
4117                 {
4118                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4119                         if (hlslshaderstring)
4120                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4121                         else
4122                                 hlslshaderstring = (char *)builtinhlslshaderstring;
4123                 }
4124                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4125                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4126                 return shaderstring;
4127         }
4128         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4129         if (shaderstring)
4130         {
4131                 if (printfromdisknotice)
4132                         Con_DPrintf("from disk %s... ", filename);
4133                 return shaderstring;
4134         }
4135         return shaderstring;
4136 }
4137
4138 #include <d3dx9.h>
4139 //#include <d3dx9shader.h>
4140 //#include <d3dx9mesh.h>
4141
4142 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4143 {
4144         DWORD *vsbin = NULL;
4145         DWORD *psbin = NULL;
4146         fs_offset_t vsbinsize;
4147         fs_offset_t psbinsize;
4148 //      IDirect3DVertexShader9 *vs = NULL;
4149 //      IDirect3DPixelShader9 *ps = NULL;
4150         ID3DXBuffer *vslog = NULL;
4151         ID3DXBuffer *vsbuffer = NULL;
4152         ID3DXConstantTable *vsconstanttable = NULL;
4153         ID3DXBuffer *pslog = NULL;
4154         ID3DXBuffer *psbuffer = NULL;
4155         ID3DXConstantTable *psconstanttable = NULL;
4156         int vsresult = 0;
4157         int psresult = 0;
4158         char temp[MAX_INPUTLINE];
4159         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4160         qboolean debugshader = gl_paranoid.integer != 0;
4161         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4162         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4163         if (!debugshader)
4164         {
4165                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4166                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4167         }
4168         if ((!vsbin && vertstring) || (!psbin && fragstring))
4169         {
4170                 const char* dllnames_d3dx9 [] =
4171                 {
4172                         "d3dx9_43.dll",
4173                         "d3dx9_42.dll",
4174                         "d3dx9_41.dll",
4175                         "d3dx9_40.dll",
4176                         "d3dx9_39.dll",
4177                         "d3dx9_38.dll",
4178                         "d3dx9_37.dll",
4179                         "d3dx9_36.dll",
4180                         "d3dx9_35.dll",
4181                         "d3dx9_34.dll",
4182                         "d3dx9_33.dll",
4183                         "d3dx9_32.dll",
4184                         "d3dx9_31.dll",
4185                         "d3dx9_30.dll",
4186                         "d3dx9_29.dll",
4187                         "d3dx9_28.dll",
4188                         "d3dx9_27.dll",
4189                         "d3dx9_26.dll",
4190                         "d3dx9_25.dll",
4191                         "d3dx9_24.dll",
4192                         NULL
4193                 };
4194                 dllhandle_t d3dx9_dll = NULL;
4195                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4196                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4197                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4198                 dllfunction_t d3dx9_dllfuncs[] =
4199                 {
4200                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4201                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4202                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4203                         {NULL, NULL}
4204                 };
4205                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4206                 {
4207                         DWORD shaderflags = 0;
4208                         if (debugshader)
4209                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4210                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4211                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4212                         if (vertstring && vertstring[0])
4213                         {
4214                                 if (debugshader)
4215                                 {
4216 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4217 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4218                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4219                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4220                                 }
4221                                 else
4222                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4223                                 if (vsbuffer)
4224                                 {
4225                                         vsbinsize = vsbuffer->GetBufferSize();
4226                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4227                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4228                                         vsbuffer->Release();
4229                                 }
4230                                 if (vslog)
4231                                 {
4232                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4233                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4234                                         vslog->Release();
4235                                 }
4236                         }
4237                         if (fragstring && fragstring[0])
4238                         {
4239                                 if (debugshader)
4240                                 {
4241 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4242 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4243                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4244                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4245                                 }
4246                                 else
4247                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4248                                 if (psbuffer)
4249                                 {
4250                                         psbinsize = psbuffer->GetBufferSize();
4251                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4252                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4253                                         psbuffer->Release();
4254                                 }
4255                                 if (pslog)
4256                                 {
4257                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4258                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4259                                         pslog->Release();
4260                                 }
4261                         }
4262                         Sys_UnloadLibrary(&d3dx9_dll);
4263                 }
4264                 else
4265                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4266         }
4267         if (vsbin && psbin)
4268         {
4269                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4270                 if (FAILED(vsresult))
4271                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4272                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4273                 if (FAILED(psresult))
4274                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4275         }
4276         // free the shader data
4277         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4278         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4279 }
4280
4281 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4282 {
4283         int i;
4284         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4285         int vertstring_length = 0;
4286         int geomstring_length = 0;
4287         int fragstring_length = 0;
4288         char *t;
4289         char *vertexstring, *geometrystring, *fragmentstring;
4290         char *vertstring, *geomstring, *fragstring;
4291         char permutationname[256];
4292         char cachename[256];
4293         int vertstrings_count = 0;
4294         int geomstrings_count = 0;
4295         int fragstrings_count = 0;
4296         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4297         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4298         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4299
4300         if (p->compiled)
4301                 return;
4302         p->compiled = true;
4303         p->vertexshader = NULL;
4304         p->pixelshader = NULL;
4305
4306         permutationname[0] = 0;
4307         cachename[0] = 0;
4308         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4309         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4310         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4311
4312         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4313         strlcat(cachename, "hlsl/", sizeof(cachename));
4314
4315         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4316         vertstrings_count = 0;
4317         geomstrings_count = 0;
4318         fragstrings_count = 0;
4319         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4320         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4321         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4322
4323         // the first pretext is which type of shader to compile as
4324         // (later these will all be bound together as a program object)
4325         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4326         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4327         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4328
4329         // the second pretext is the mode (for example a light source)
4330         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4331         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4332         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4333         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4334         strlcat(cachename, modeinfo->name, sizeof(cachename));
4335
4336         // now add all the permutation pretexts
4337         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4338         {
4339                 if (permutation & (1<<i))
4340                 {
4341                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4342                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4343                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4344                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4345                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4346                 }
4347                 else
4348                 {
4349                         // keep line numbers correct
4350                         vertstrings_list[vertstrings_count++] = "\n";
4351                         geomstrings_list[geomstrings_count++] = "\n";
4352                         fragstrings_list[fragstrings_count++] = "\n";
4353                 }
4354         }
4355
4356         // add static parms
4357         R_CompileShader_AddStaticParms(mode, permutation);
4358         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4359         vertstrings_count += shaderstaticparms_count;
4360         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4361         geomstrings_count += shaderstaticparms_count;
4362         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4363         fragstrings_count += shaderstaticparms_count;
4364
4365         // replace spaces in the cachename with _ characters
4366         for (i = 0;cachename[i];i++)
4367                 if (cachename[i] == ' ')
4368                         cachename[i] = '_';
4369
4370         // now append the shader text itself
4371         vertstrings_list[vertstrings_count++] = vertexstring;
4372         geomstrings_list[geomstrings_count++] = geometrystring;
4373         fragstrings_list[fragstrings_count++] = fragmentstring;
4374
4375         // if any sources were NULL, clear the respective list
4376         if (!vertexstring)
4377                 vertstrings_count = 0;
4378         if (!geometrystring)
4379                 geomstrings_count = 0;
4380         if (!fragmentstring)
4381                 fragstrings_count = 0;
4382
4383         vertstring_length = 0;
4384         for (i = 0;i < vertstrings_count;i++)
4385                 vertstring_length += strlen(vertstrings_list[i]);
4386         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4387         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4388                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4389
4390         geomstring_length = 0;
4391         for (i = 0;i < geomstrings_count;i++)
4392                 geomstring_length += strlen(geomstrings_list[i]);
4393         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4394         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4395                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4396
4397         fragstring_length = 0;
4398         for (i = 0;i < fragstrings_count;i++)
4399                 fragstring_length += strlen(fragstrings_list[i]);
4400         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4401         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4402                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4403
4404         // try to load the cached shader, or generate one
4405         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4406
4407         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4408                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4409         else
4410                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4411
4412         // free the strings
4413         if (vertstring)
4414                 Mem_Free(vertstring);
4415         if (geomstring)
4416                 Mem_Free(geomstring);
4417         if (fragstring)
4418                 Mem_Free(fragstring);
4419         if (vertexstring)
4420                 Mem_Free(vertexstring);
4421         if (geometrystring)
4422                 Mem_Free(geometrystring);
4423         if (fragmentstring)
4424                 Mem_Free(fragmentstring);
4425 }
4426
4427 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4428 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4429 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);}
4430 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);}
4431 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);}
4432 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);}
4433
4434 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4435 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4436 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);}
4437 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);}
4438 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);}
4439 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);}
4440
4441 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4442 {
4443         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4444         if (r_hlsl_permutation != perm)
4445         {
4446                 r_hlsl_permutation = perm;
4447                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4448                 {
4449                         if (!r_hlsl_permutation->compiled)
4450                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4451                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4452                         {
4453                                 // remove features until we find a valid permutation
4454                                 int i;
4455                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4456                                 {
4457                                         // reduce i more quickly whenever it would not remove any bits
4458                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4459                                         if (!(permutation & j))
4460                                                 continue;
4461                                         permutation -= j;
4462                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4463                                         if (!r_hlsl_permutation->compiled)
4464                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4465                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4466                                                 break;
4467                                 }
4468                                 if (i >= SHADERPERMUTATION_COUNT)
4469                                 {
4470                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4471                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4472                                         return; // no bit left to clear, entire mode is broken
4473                                 }
4474                         }
4475                 }
4476                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4477                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4478         }
4479         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4480         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4481         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4482 }
4483 #endif
4484
4485 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4486 {
4487         DPSOFTRAST_SetShader(mode, permutation);
4488         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4489         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4490         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4491 }
4492
4493 void R_GLSL_Restart_f(void)
4494 {
4495         unsigned int i, limit;
4496         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4497                 Mem_Free(glslshaderstring);
4498         glslshaderstring = NULL;
4499         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
4500                 Mem_Free(hlslshaderstring);
4501         hlslshaderstring = NULL;
4502         switch(vid.renderpath)
4503         {
4504         case RENDERPATH_D3D9:
4505 #ifdef SUPPORTD3D
4506                 {
4507                         r_hlsl_permutation_t *p;
4508                         r_hlsl_permutation = NULL;
4509                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4510                         for (i = 0;i < limit;i++)
4511                         {
4512                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4513                                 {
4514                                         if (p->vertexshader)
4515                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4516                                         if (p->pixelshader)
4517                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4518                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4519                                 }
4520                         }
4521                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4522                 }
4523 #endif
4524                 break;
4525         case RENDERPATH_D3D10:
4526                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4527                 break;
4528         case RENDERPATH_D3D11:
4529                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4530                 break;
4531         case RENDERPATH_GL20:
4532         case RENDERPATH_GLES2:
4533                 {
4534                         r_glsl_permutation_t *p;
4535                         r_glsl_permutation = NULL;
4536                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4537                         for (i = 0;i < limit;i++)
4538                         {
4539                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4540                                 {
4541                                         GL_Backend_FreeProgram(p->program);
4542                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4543                                 }
4544                         }
4545                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4546                 }
4547                 break;
4548         case RENDERPATH_GL13:
4549         case RENDERPATH_GL11:
4550                 break;
4551         case RENDERPATH_SOFT:
4552                 break;
4553         }
4554 }
4555
4556 void R_GLSL_DumpShader_f(void)
4557 {
4558         int i;
4559         qfile_t *file;
4560
4561         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4562         if (file)
4563         {
4564                 FS_Print(file, "/* The engine may define the following macros:\n");
4565                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4566                 for (i = 0;i < SHADERMODE_COUNT;i++)
4567                         FS_Print(file, glslshadermodeinfo[i].pretext);
4568                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4569                         FS_Print(file, shaderpermutationinfo[i].pretext);
4570                 FS_Print(file, "*/\n");
4571                 FS_Print(file, builtinshaderstring);
4572                 FS_Close(file);
4573                 Con_Printf("glsl/default.glsl written\n");
4574         }
4575         else
4576                 Con_Printf("failed to write to glsl/default.glsl\n");
4577
4578         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4579         if (file)
4580         {
4581                 FS_Print(file, "/* The engine may define the following macros:\n");
4582                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4583                 for (i = 0;i < SHADERMODE_COUNT;i++)
4584                         FS_Print(file, hlslshadermodeinfo[i].pretext);
4585                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4586                         FS_Print(file, shaderpermutationinfo[i].pretext);
4587                 FS_Print(file, "*/\n");
4588                 FS_Print(file, builtinhlslshaderstring);
4589                 FS_Close(file);
4590                 Con_Printf("hlsl/default.hlsl written\n");
4591         }
4592         else
4593                 Con_Printf("failed to write to hlsl/default.hlsl\n");
4594 }
4595
4596 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4597 {
4598         if (!second)
4599                 texturemode = GL_MODULATE;
4600         switch (vid.renderpath)
4601         {
4602         case RENDERPATH_D3D9:
4603 #ifdef SUPPORTD3D
4604                 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))));
4605                 R_Mesh_TexBind(GL20TU_FIRST , first );
4606                 R_Mesh_TexBind(GL20TU_SECOND, second);
4607 #endif
4608                 break;
4609         case RENDERPATH_D3D10:
4610                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4611                 break;
4612         case RENDERPATH_D3D11:
4613                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4614                 break;
4615         case RENDERPATH_GL20:
4616         case RENDERPATH_GLES2:
4617                 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))));
4618                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
4619                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
4620                 break;
4621         case RENDERPATH_GL13:
4622                 R_Mesh_TexBind(0, first );
4623                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4624                 R_Mesh_TexBind(1, second);
4625                 if (second)
4626                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4627                 break;
4628         case RENDERPATH_GL11:
4629                 R_Mesh_TexBind(0, first );
4630                 break;
4631         case RENDERPATH_SOFT:
4632                 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))));
4633                 R_Mesh_TexBind(GL20TU_FIRST , first );
4634                 R_Mesh_TexBind(GL20TU_SECOND, second);
4635                 break;
4636         }
4637 }
4638
4639 void R_SetupShader_DepthOrShadow(void)
4640 {
4641         switch (vid.renderpath)
4642         {
4643         case RENDERPATH_D3D9:
4644 #ifdef SUPPORTD3D
4645                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4646 #endif
4647                 break;
4648         case RENDERPATH_D3D10:
4649                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4650                 break;
4651         case RENDERPATH_D3D11:
4652                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4653                 break;
4654         case RENDERPATH_GL20:
4655         case RENDERPATH_GLES2:
4656                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4657                 break;
4658         case RENDERPATH_GL13:
4659                 R_Mesh_TexBind(0, 0);
4660                 R_Mesh_TexBind(1, 0);
4661                 break;
4662         case RENDERPATH_GL11:
4663                 R_Mesh_TexBind(0, 0);
4664                 break;
4665         case RENDERPATH_SOFT:
4666                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
4667                 break;
4668         }
4669 }
4670
4671 void R_SetupShader_ShowDepth(void)
4672 {
4673         switch (vid.renderpath)
4674         {
4675         case RENDERPATH_D3D9:
4676 #ifdef SUPPORTHLSL
4677                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
4678 #endif
4679                 break;
4680         case RENDERPATH_D3D10:
4681                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4682                 break;
4683         case RENDERPATH_D3D11:
4684                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4685                 break;
4686         case RENDERPATH_GL20:
4687         case RENDERPATH_GLES2:
4688                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4689                 break;
4690         case RENDERPATH_GL13:
4691                 break;
4692         case RENDERPATH_GL11:
4693                 break;
4694         case RENDERPATH_SOFT:
4695                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
4696                 break;
4697         }
4698 }
4699
4700 extern qboolean r_shadow_usingdeferredprepass;
4701 extern cvar_t r_shadow_deferred_8bitrange;
4702 extern rtexture_t *r_shadow_attenuationgradienttexture;
4703 extern rtexture_t *r_shadow_attenuation2dtexture;
4704 extern rtexture_t *r_shadow_attenuation3dtexture;
4705 extern qboolean r_shadow_usingshadowmap2d;
4706 extern qboolean r_shadow_usingshadowmaportho;
4707 extern float r_shadow_shadowmap_texturescale[2];
4708 extern float r_shadow_shadowmap_parameters[4];
4709 extern qboolean r_shadow_shadowmapvsdct;
4710 extern qboolean r_shadow_shadowmapsampler;
4711 extern int r_shadow_shadowmappcf;
4712 extern rtexture_t *r_shadow_shadowmap2dtexture;
4713 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
4714 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4715 extern matrix4x4_t r_shadow_shadowmapmatrix;
4716 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4717 extern int r_shadow_prepass_width;
4718 extern int r_shadow_prepass_height;
4719 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4720 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4721 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
4722 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4723 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4724 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4725 {
4726         // a blendfunc allows colormod if:
4727         // a) it can never keep the destination pixel invariant, or
4728         // b) it can keep the destination pixel invariant, and still can do so if colormodded
4729         // this is to prevent unintended side effects from colormod
4730
4731         // in formulas:
4732         // IF there is a (s, sa) for which for all (d, da),
4733         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4734         // THEN, for this (s, sa) and all (colormod, d, da):
4735         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4736         // OBVIOUSLY, this means that
4737         //   s*colormod * src(s*colormod, d, sa, da) = 0
4738         //   dst(s*colormod, d, sa, da)              = 1
4739
4740         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4741
4742         // main condition to leave dst color invariant:
4743         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4744         //   src == GL_ZERO:
4745         //     s * 0 + d * dst(s, d, sa, da) == d
4746         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4747         //       => colormod is a problem for GL_SRC_COLOR only
4748         //   src == GL_ONE:
4749         //     s + d * dst(s, d, sa, da) == d
4750         //       => s == 0
4751         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4752         //       => colormod is never problematic for these
4753         //   src == GL_SRC_COLOR:
4754         //     s*s + d * dst(s, d, sa, da) == d
4755         //       => s == 0
4756         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4757         //       => colormod is never problematic for these
4758         //   src == GL_ONE_MINUS_SRC_COLOR:
4759         //     s*(1-s) + d * dst(s, d, sa, da) == d
4760         //       => s == 0 or s == 1
4761         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4762         //       => colormod is a problem for GL_SRC_COLOR only
4763         //   src == GL_DST_COLOR
4764         //     s*d + d * dst(s, d, sa, da) == d
4765         //       => s == 1
4766         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4767         //       => colormod is always a problem
4768         //     or
4769         //       => s == 0
4770         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4771         //       => colormod is never problematic for these
4772         //       => BUT, we do not know s! We must assume it is problematic
4773         //       then... except in GL_ONE case, where we know all invariant
4774         //       cases are fine
4775         //   src == GL_ONE_MINUS_DST_COLOR
4776         //     s*(1-d) + d * dst(s, d, sa, da) == d
4777         //       => s == 0 (1-d is impossible to handle for our desired result)
4778         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4779         //       => colormod is never problematic for these
4780         //   src == GL_SRC_ALPHA
4781         //     s*sa + d * dst(s, d, sa, da) == d
4782         //       => s == 0, or sa == 0
4783         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4784         //       => colormod breaks in the case GL_SRC_COLOR only
4785         //   src == GL_ONE_MINUS_SRC_ALPHA
4786         //     s*(1-sa) + d * dst(s, d, sa, da) == d
4787         //       => s == 0, or sa == 1
4788         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4789         //       => colormod breaks in the case GL_SRC_COLOR only
4790         //   src == GL_DST_ALPHA
4791         //     s*da + d * dst(s, d, sa, da) == d
4792         //       => s == 0
4793         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4794         //       => colormod is never problematic for these
4795
4796         switch(src)
4797         {
4798                 case GL_ZERO:
4799                 case GL_ONE_MINUS_SRC_COLOR:
4800                 case GL_SRC_ALPHA:
4801                 case GL_ONE_MINUS_SRC_ALPHA:
4802                         if(dst == GL_SRC_COLOR)
4803                                 return false;
4804                         return true;
4805                 case GL_ONE:
4806                 case GL_SRC_COLOR:
4807                 case GL_ONE_MINUS_DST_COLOR:
4808                 case GL_DST_ALPHA:
4809                 case GL_ONE_MINUS_DST_ALPHA:
4810                         return true;
4811                 case GL_DST_COLOR:
4812                         if(dst == GL_ONE)
4813                                 return true;
4814                         return false;
4815                 default:
4816                         return false;
4817         }
4818 }
4819 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)
4820 {
4821         // select a permutation of the lighting shader appropriate to this
4822         // combination of texture, entity, light source, and fogging, only use the
4823         // minimum features necessary to avoid wasting rendering time in the
4824         // fragment shader on features that are not being used
4825         unsigned int permutation = 0;
4826         unsigned int mode = 0;
4827         qboolean allow_colormod;
4828         static float dummy_colormod[3] = {1, 1, 1};
4829         float *colormod = rsurface.colormod;
4830         float m16f[16];
4831         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
4832         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4833                 permutation |= SHADERPERMUTATION_ALPHAKILL;
4834         if (rsurfacepass == RSURFPASS_BACKGROUND)
4835         {
4836                 // distorted background
4837                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4838                 {
4839                         mode = SHADERMODE_WATER;
4840                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4841                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4842                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
4843                         {
4844                                 // this is the right thing to do for wateralpha
4845                                 GL_BlendFunc(GL_ONE, GL_ZERO);
4846                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4847                         }
4848                         else
4849                         {
4850                                 // this is the right thing to do for entity alpha
4851                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4852                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4853                         }
4854                 }
4855                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4856                 {
4857                         mode = SHADERMODE_REFRACTION;
4858                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4859                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4860                 }
4861                 else
4862                 {
4863                         mode = SHADERMODE_GENERIC;
4864                         permutation |= SHADERPERMUTATION_DIFFUSE;
4865                         GL_BlendFunc(GL_ONE, GL_ZERO);
4866                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4867                 }
4868         }
4869         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4870         {
4871                 if (r_glsl_offsetmapping.integer)
4872                 {
4873                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4874                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4875                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4876                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4877                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4878                         {
4879                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4880                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4881                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4882                         }
4883                 }
4884                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4885                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4886                 // normalmap (deferred prepass), may use alpha test on diffuse
4887                 mode = SHADERMODE_DEFERREDGEOMETRY;
4888                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4889                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4890                 GL_BlendFunc(GL_ONE, GL_ZERO);
4891                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4892         }
4893         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4894         {
4895                 if (r_glsl_offsetmapping.integer)
4896                 {
4897                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4898                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4899                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4900                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4901                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4902                         {
4903                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4904                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4905                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4906                         }
4907                 }
4908                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4909                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4910                 // light source
4911                 mode = SHADERMODE_LIGHTSOURCE;
4912                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4913                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4914                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4915                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4916                 if (diffusescale > 0)
4917                         permutation |= SHADERPERMUTATION_DIFFUSE;
4918                 if (specularscale > 0)
4919                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4920                 if (r_refdef.fogenabled)
4921                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4922                 if (rsurface.texture->colormapping)
4923                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4924                 if (r_shadow_usingshadowmap2d)
4925                 {
4926                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4927                         if(r_shadow_shadowmapvsdct)
4928                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4929
4930                         if (r_shadow_shadowmapsampler)
4931                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4932                         if (r_shadow_shadowmappcf > 1)
4933                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4934                         else if (r_shadow_shadowmappcf)
4935                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4936                 }
4937                 if (rsurface.texture->reflectmasktexture)
4938                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4939                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4940                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
4941         }
4942         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4943         {
4944                 if (r_glsl_offsetmapping.integer)
4945                 {
4946                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4947                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4948                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4949                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4950                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4951                         {
4952                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4953                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4954                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4955                         }
4956                 }
4957                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4958                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4959                 // unshaded geometry (fullbright or ambient model lighting)
4960                 mode = SHADERMODE_FLATCOLOR;
4961                 ambientscale = diffusescale = specularscale = 0;
4962                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4963                         permutation |= SHADERPERMUTATION_GLOW;
4964                 if (r_refdef.fogenabled)
4965                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4966                 if (rsurface.texture->colormapping)
4967                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4968                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4969                 {
4970                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4971                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4972
4973                         if (r_shadow_shadowmapsampler)
4974                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4975                         if (r_shadow_shadowmappcf > 1)
4976                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4977                         else if (r_shadow_shadowmappcf)
4978                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4979                 }
4980                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4981                         permutation |= SHADERPERMUTATION_REFLECTION;
4982                 if (rsurface.texture->reflectmasktexture)
4983                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4984                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4985                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4986         }
4987         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4988         {
4989                 if (r_glsl_offsetmapping.integer)
4990                 {
4991                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4992                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4993                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4994                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4995                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4996                         {
4997                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4998                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4999                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5000                         }
5001                 }
5002                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5003                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5004                 // directional model lighting
5005                 mode = SHADERMODE_LIGHTDIRECTION;
5006                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5007                         permutation |= SHADERPERMUTATION_GLOW;
5008                 permutation |= SHADERPERMUTATION_DIFFUSE;
5009                 if (specularscale > 0)
5010                         permutation |= SHADERPERMUTATION_SPECULAR;
5011                 if (r_refdef.fogenabled)
5012                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5013                 if (rsurface.texture->colormapping)
5014                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5015                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5016                 {
5017                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5018                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5019
5020                         if (r_shadow_shadowmapsampler)
5021                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5022                         if (r_shadow_shadowmappcf > 1)
5023                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5024                         else if (r_shadow_shadowmappcf)
5025                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5026                 }
5027                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5028                         permutation |= SHADERPERMUTATION_REFLECTION;
5029                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5030                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5031                 if (rsurface.texture->reflectmasktexture)
5032                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5033                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5034                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5035         }
5036         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5037         {
5038                 if (r_glsl_offsetmapping.integer)
5039                 {
5040                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5041                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5042                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5043                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5044                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5045                         {
5046                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5047                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5048                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5049                         }
5050                 }
5051                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5052                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5053                 // ambient model lighting
5054                 mode = SHADERMODE_LIGHTDIRECTION;
5055                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5056                         permutation |= SHADERPERMUTATION_GLOW;
5057                 if (r_refdef.fogenabled)
5058                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5059                 if (rsurface.texture->colormapping)
5060                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5061                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5062                 {
5063                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5064                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5065
5066                         if (r_shadow_shadowmapsampler)
5067                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5068                         if (r_shadow_shadowmappcf > 1)
5069                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5070                         else if (r_shadow_shadowmappcf)
5071                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5072                 }
5073                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5074                         permutation |= SHADERPERMUTATION_REFLECTION;
5075                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5076                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5077                 if (rsurface.texture->reflectmasktexture)
5078                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5079                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5080                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5081         }
5082         else
5083         {
5084                 if (r_glsl_offsetmapping.integer)
5085                 {
5086                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5087                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5088                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5089                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5090                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5091                         {
5092                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5093                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5094                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5095                         }
5096                 }
5097                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5098                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5099                 // lightmapped wall
5100                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5101                         permutation |= SHADERPERMUTATION_GLOW;
5102                 if (r_refdef.fogenabled)
5103                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5104                 if (rsurface.texture->colormapping)
5105                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5106                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5107                 {
5108                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5109                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5110
5111                         if (r_shadow_shadowmapsampler)
5112                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5113                         if (r_shadow_shadowmappcf > 1)
5114                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5115                         else if (r_shadow_shadowmappcf)
5116                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5117                 }
5118                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5119                         permutation |= SHADERPERMUTATION_REFLECTION;
5120                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5121                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5122                 if (rsurface.texture->reflectmasktexture)
5123                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5124                 if (FAKELIGHT_ENABLED)
5125                 {
5126                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5127                         mode = SHADERMODE_FAKELIGHT;
5128                         permutation |= SHADERPERMUTATION_DIFFUSE;
5129                         if (specularscale > 0)
5130                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5131                 }
5132                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5133                 {
5134                         // deluxemapping (light direction texture)
5135                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5136                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5137                         else
5138                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5139                         permutation |= SHADERPERMUTATION_DIFFUSE;
5140                         if (specularscale > 0)
5141                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5142                 }
5143                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5144                 {
5145                         // fake deluxemapping (uniform light direction in tangentspace)
5146                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5147                         permutation |= SHADERPERMUTATION_DIFFUSE;
5148                         if (specularscale > 0)
5149                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5150                 }
5151                 else if (rsurface.uselightmaptexture)
5152                 {
5153                         // ordinary lightmapping (q1bsp, q3bsp)
5154                         mode = SHADERMODE_LIGHTMAP;
5155                 }
5156                 else
5157                 {
5158                         // ordinary vertex coloring (q3bsp)
5159                         mode = SHADERMODE_VERTEXCOLOR;
5160                 }
5161                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5162                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5163         }
5164         if(!allow_colormod)
5165                 colormod = dummy_colormod;
5166         switch(vid.renderpath)
5167         {
5168         case RENDERPATH_D3D9:
5169 #ifdef SUPPORTD3D
5170                 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);
5171                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5172                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5173                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5174                 if (mode == SHADERMODE_LIGHTSOURCE)
5175                 {
5176                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5177                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5178                 }
5179                 else
5180                 {
5181                         if (mode == SHADERMODE_LIGHTDIRECTION)
5182                         {
5183                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5184                         }
5185                 }
5186                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5187                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5188                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5189                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5190                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5191
5192                 if (mode == SHADERMODE_LIGHTSOURCE)
5193                 {
5194                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5195                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5196                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5197                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5198                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5199
5200                         // additive passes are only darkened by fog, not tinted
5201                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5202                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5203                 }
5204                 else
5205                 {
5206                         if (mode == SHADERMODE_FLATCOLOR)
5207                         {
5208                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5209                         }
5210                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5211                         {
5212                                 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]);
5213                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5214                                 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);
5215                                 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);
5216                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5217                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5218                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5219                         }
5220                         else
5221                         {
5222                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5223                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5224                                 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);
5225                                 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);
5226                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5227                         }
5228                         // additive passes are only darkened by fog, not tinted
5229                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5230                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5231                         else
5232                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5233                         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);
5234                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5235                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5236                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5237                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5238                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5239                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5240                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5241                         if (mode == SHADERMODE_WATER)
5242                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5243                 }
5244                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5245                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5246                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5247                 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));
5248                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5249                 if (rsurface.texture->pantstexture)
5250                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5251                 else
5252                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5253                 if (rsurface.texture->shirttexture)
5254                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5255                 else
5256                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5257                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5258                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5259                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5260                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5261                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5262                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5263                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5264
5265                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5266                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5267                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5268                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5269                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5270                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5271                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5272                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5273                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5274                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5275                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5276                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5277                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5278                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5279                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5280                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5281                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5282                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5283                 {
5284                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5285                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5286                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5287                 }
5288                 else
5289                 {
5290                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5291                 }
5292 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5293 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5294                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5295                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5296                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5297                 {
5298                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5299                         if (rsurface.rtlight)
5300                         {
5301                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5302                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5303                         }
5304                 }
5305 #endif
5306                 break;
5307         case RENDERPATH_D3D10:
5308                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5309                 break;
5310         case RENDERPATH_D3D11:
5311                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5312                 break;
5313         case RENDERPATH_GL20:
5314         case RENDERPATH_GLES2:
5315                 if (!vid.useinterleavedarrays)
5316                 {
5317                         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);
5318                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5319                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5320                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5321                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5322                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5323                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5324                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5325                 }
5326                 else
5327                 {
5328                         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);
5329                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5330                 }
5331                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5332                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5333                 if (mode == SHADERMODE_LIGHTSOURCE)
5334                 {
5335                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5336                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5337                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5338                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5339                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5340                         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);
5341         
5342                         // additive passes are only darkened by fog, not tinted
5343                         if (r_glsl_permutation->loc_FogColor >= 0)
5344                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5345                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5346                 }
5347                 else
5348                 {
5349                         if (mode == SHADERMODE_FLATCOLOR)
5350                         {
5351                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5352                         }
5353                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5354                         {
5355                                 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]);
5356                                 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]);
5357                                 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);
5358                                 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);
5359                                 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);
5360                                 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]);
5361                                 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]);
5362                         }
5363                         else
5364                         {
5365                                 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]);
5366                                 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]);
5367                                 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);
5368                                 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);
5369                                 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);
5370                         }
5371                         // additive passes are only darkened by fog, not tinted
5372                         if (r_glsl_permutation->loc_FogColor >= 0)
5373                         {
5374                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5375                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5376                                 else
5377                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5378                         }
5379                         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);
5380                         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]);
5381                         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]);
5382                         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]);
5383                         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]);
5384                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5385                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5386                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5387                         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]);
5388                 }
5389                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5390                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5391                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5392                 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]);
5393                 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]);
5394
5395                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5396                 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));
5397                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5398                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5399                 {
5400                         if (rsurface.texture->pantstexture)
5401                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5402                         else
5403                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5404                 }
5405                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5406                 {
5407                         if (rsurface.texture->shirttexture)
5408                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5409                         else
5410                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5411                 }
5412                 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]);
5413                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5414                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5415                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5416                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5417                 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]);
5418                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5419
5420                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
5421                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
5422                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
5423                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
5424                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
5425                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
5426                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
5427                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
5428                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
5429                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
5430                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
5431                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
5432                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
5433                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
5434                 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);
5435                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
5436                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
5437                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5438                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5439                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
5440                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5441                 {
5442                         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);
5443                         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);
5444                         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);
5445                 }
5446                 else
5447                 {
5448                         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);
5449                 }
5450                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
5451                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
5452                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
5453                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
5454                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5455                 {
5456                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
5457                         if (rsurface.rtlight)
5458                         {
5459                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
5460                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
5461                         }
5462                 }
5463                 CHECKGLERROR
5464                 break;
5465         case RENDERPATH_GL13:
5466         case RENDERPATH_GL11:
5467                 break;
5468         case RENDERPATH_SOFT:
5469                 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);
5470                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
5471                 R_SetupShader_SetPermutationSoft(mode, permutation);
5472                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
5473                 if (mode == SHADERMODE_LIGHTSOURCE)
5474                 {
5475                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
5476                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5477                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5478                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5479                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5480                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5481         
5482                         // additive passes are only darkened by fog, not tinted
5483                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5484                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5485                 }
5486                 else
5487                 {
5488                         if (mode == SHADERMODE_FLATCOLOR)
5489                         {
5490                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5491                         }
5492                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5493                         {
5494                                 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]);
5495                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5496                                 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);
5497                                 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);
5498                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5499                                 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]);
5500                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5501                         }
5502                         else
5503                         {
5504                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5505                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5506                                 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);
5507                                 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);
5508                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5509                         }
5510                         // additive passes are only darkened by fog, not tinted
5511                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5512                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5513                         else
5514                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5515                         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);
5516                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5517                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5518                         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]);
5519                         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]);
5520                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5521                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
5522                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5523                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5524                 }
5525                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
5526                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
5527                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
5528                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5529                 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]);
5530
5531                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5532                 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));
5533                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5534                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
5535                 {
5536                         if (rsurface.texture->pantstexture)
5537                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5538                         else
5539                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
5540                 }
5541                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
5542                 {
5543                         if (rsurface.texture->shirttexture)
5544                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5545                         else
5546                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
5547                 }
5548                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5549                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
5550                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
5551                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
5552                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5553                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5554                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5555
5556                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5557                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5558                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5559                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5560                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5561                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5562                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5563                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5564                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5565                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5566                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5567                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5568                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5569                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5570                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5571                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5572                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5573                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5574                 {
5575                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5576                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5577                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5578                 }
5579                 else
5580                 {
5581                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5582                 }
5583 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5584 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5585                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5586                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5587                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5588                 {
5589                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5590                         if (rsurface.rtlight)
5591                         {
5592                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5593                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5594                         }
5595                 }
5596                 break;
5597         }
5598 }
5599
5600 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5601 {
5602         // select a permutation of the lighting shader appropriate to this
5603         // combination of texture, entity, light source, and fogging, only use the
5604         // minimum features necessary to avoid wasting rendering time in the
5605         // fragment shader on features that are not being used
5606         unsigned int permutation = 0;
5607         unsigned int mode = 0;
5608         const float *lightcolorbase = rtlight->currentcolor;
5609         float ambientscale = rtlight->ambientscale;
5610         float diffusescale = rtlight->diffusescale;
5611         float specularscale = rtlight->specularscale;
5612         // this is the location of the light in view space
5613         vec3_t viewlightorigin;
5614         // this transforms from view space (camera) to light space (cubemap)
5615         matrix4x4_t viewtolight;
5616         matrix4x4_t lighttoview;
5617         float viewtolight16f[16];
5618         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5619         // light source
5620         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5621         if (rtlight->currentcubemap != r_texture_whitecube)
5622                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5623         if (diffusescale > 0)
5624                 permutation |= SHADERPERMUTATION_DIFFUSE;
5625         if (specularscale > 0)
5626                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5627         if (r_shadow_usingshadowmap2d)
5628         {
5629                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5630                 if (r_shadow_shadowmapvsdct)
5631                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5632
5633                 if (r_shadow_shadowmapsampler)
5634                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5635                 if (r_shadow_shadowmappcf > 1)
5636                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5637                 else if (r_shadow_shadowmappcf)
5638                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5639         }
5640         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5641         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5642         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5643         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5644         switch(vid.renderpath)
5645         {
5646         case RENDERPATH_D3D9:
5647 #ifdef SUPPORTD3D
5648                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5649                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5650                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
5651                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5652                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5653                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5654                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5655                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5656                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5657                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5658                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5659
5660                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5661                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
5662                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5663                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5664                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
5665                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5666 #endif
5667                 break;
5668         case RENDERPATH_D3D10:
5669                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5670                 break;
5671         case RENDERPATH_D3D11:
5672                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5673                 break;
5674         case RENDERPATH_GL20:
5675         case RENDERPATH_GLES2:
5676                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5677                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5678                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5679                 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);
5680                 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);
5681                 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);
5682                 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]);
5683                 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]);
5684                 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));
5685                 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]);
5686                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
5687
5688                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
5689                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
5690                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
5691                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
5692                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
5693                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
5694                 break;
5695         case RENDERPATH_GL13:
5696         case RENDERPATH_GL11:
5697                 break;
5698         case RENDERPATH_SOFT:
5699                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5700                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5701                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
5702                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5703                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5704                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5705                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5706                 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]);
5707                 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));
5708                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5709                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5710
5711                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5712                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5713                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5714                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5715                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5716                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5717                 break;
5718         }
5719 }
5720
5721 #define SKINFRAME_HASH 1024
5722
5723 typedef struct
5724 {
5725         int loadsequence; // incremented each level change
5726         memexpandablearray_t array;
5727         skinframe_t *hash[SKINFRAME_HASH];
5728 }
5729 r_skinframe_t;
5730 r_skinframe_t r_skinframe;
5731
5732 void R_SkinFrame_PrepareForPurge(void)
5733 {
5734         r_skinframe.loadsequence++;
5735         // wrap it without hitting zero
5736         if (r_skinframe.loadsequence >= 200)
5737                 r_skinframe.loadsequence = 1;
5738 }
5739
5740 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5741 {
5742         if (!skinframe)
5743                 return;
5744         // mark the skinframe as used for the purging code
5745         skinframe->loadsequence = r_skinframe.loadsequence;
5746 }
5747
5748 void R_SkinFrame_Purge(void)
5749 {
5750         int i;
5751         skinframe_t *s;
5752         for (i = 0;i < SKINFRAME_HASH;i++)
5753         {
5754                 for (s = r_skinframe.hash[i];s;s = s->next)
5755                 {
5756                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5757                         {
5758                                 if (s->merged == s->base)
5759                                         s->merged = NULL;
5760                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5761                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5762                                 R_PurgeTexture(s->merged);s->merged = NULL;
5763                                 R_PurgeTexture(s->base  );s->base   = NULL;
5764                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5765                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5766                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5767                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5768                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5769                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5770                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5771                                 s->loadsequence = 0;
5772                         }
5773                 }
5774         }
5775 }
5776
5777 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5778         skinframe_t *item;
5779         char basename[MAX_QPATH];
5780
5781         Image_StripImageExtension(name, basename, sizeof(basename));
5782
5783         if( last == NULL ) {
5784                 int hashindex;
5785                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5786                 item = r_skinframe.hash[hashindex];
5787         } else {
5788                 item = last->next;
5789         }
5790
5791         // linearly search through the hash bucket
5792         for( ; item ; item = item->next ) {
5793                 if( !strcmp( item->basename, basename ) ) {
5794                         return item;
5795                 }
5796         }
5797         return NULL;
5798 }
5799
5800 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5801 {
5802         skinframe_t *item;
5803         int hashindex;
5804         char basename[MAX_QPATH];
5805
5806         Image_StripImageExtension(name, basename, sizeof(basename));
5807
5808         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5809         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5810                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5811                         break;
5812
5813         if (!item) {
5814                 rtexture_t *dyntexture;
5815                 // check whether its a dynamic texture
5816                 dyntexture = CL_GetDynTexture( basename );
5817                 if (!add && !dyntexture)
5818                         return NULL;
5819                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5820                 memset(item, 0, sizeof(*item));
5821                 strlcpy(item->basename, basename, sizeof(item->basename));
5822                 item->base = dyntexture; // either NULL or dyntexture handle
5823                 item->textureflags = textureflags;
5824                 item->comparewidth = comparewidth;
5825                 item->compareheight = compareheight;
5826                 item->comparecrc = comparecrc;
5827                 item->next = r_skinframe.hash[hashindex];
5828                 r_skinframe.hash[hashindex] = item;
5829         }
5830         else if( item->base == NULL )
5831         {
5832                 rtexture_t *dyntexture;
5833                 // check whether its a dynamic texture
5834                 // 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]
5835                 dyntexture = CL_GetDynTexture( basename );
5836                 item->base = dyntexture; // either NULL or dyntexture handle
5837         }
5838
5839         R_SkinFrame_MarkUsed(item);
5840         return item;
5841 }
5842
5843 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5844         { \
5845                 unsigned long long avgcolor[5], wsum; \
5846                 int pix, comp, w; \
5847                 avgcolor[0] = 0; \
5848                 avgcolor[1] = 0; \
5849                 avgcolor[2] = 0; \
5850                 avgcolor[3] = 0; \
5851                 avgcolor[4] = 0; \
5852                 wsum = 0; \
5853                 for(pix = 0; pix < cnt; ++pix) \
5854                 { \
5855                         w = 0; \
5856                         for(comp = 0; comp < 3; ++comp) \
5857                                 w += getpixel; \
5858                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5859                         { \
5860                                 ++wsum; \
5861                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5862                                 w = getpixel; \
5863                                 for(comp = 0; comp < 3; ++comp) \
5864                                         avgcolor[comp] += getpixel * w; \
5865                                 avgcolor[3] += w; \
5866                         } \
5867                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5868                         avgcolor[4] += getpixel; \
5869                 } \
5870                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5871                         avgcolor[3] = 1; \
5872                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5873                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5874                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5875                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5876         }
5877
5878 extern cvar_t gl_picmip;
5879 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5880 {
5881         int j;
5882         unsigned char *pixels;
5883         unsigned char *bumppixels;
5884         unsigned char *basepixels = NULL;
5885         int basepixels_width = 0;
5886         int basepixels_height = 0;
5887         skinframe_t *skinframe;
5888         rtexture_t *ddsbase = NULL;
5889         qboolean ddshasalpha = false;
5890         float ddsavgcolor[4];
5891         char basename[MAX_QPATH];
5892         int miplevel = R_PicmipForFlags(textureflags);
5893         int savemiplevel = miplevel;
5894         int mymiplevel;
5895
5896         if (cls.state == ca_dedicated)
5897                 return NULL;
5898
5899         // return an existing skinframe if already loaded
5900         // if loading of the first image fails, don't make a new skinframe as it
5901         // would cause all future lookups of this to be missing
5902         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5903         if (skinframe && skinframe->base)
5904                 return skinframe;
5905
5906         Image_StripImageExtension(name, basename, sizeof(basename));
5907
5908         // check for DDS texture file first
5909         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5910         {
5911                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
5912                 if (basepixels == NULL)
5913                         return NULL;
5914         }
5915
5916         // FIXME handle miplevel
5917
5918         if (developer_loading.integer)
5919                 Con_Printf("loading skin \"%s\"\n", name);
5920
5921         // we've got some pixels to store, so really allocate this new texture now
5922         if (!skinframe)
5923                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5924         skinframe->stain = NULL;
5925         skinframe->merged = NULL;
5926         skinframe->base = NULL;
5927         skinframe->pants = NULL;
5928         skinframe->shirt = NULL;
5929         skinframe->nmap = NULL;
5930         skinframe->gloss = NULL;
5931         skinframe->glow = NULL;
5932         skinframe->fog = NULL;
5933         skinframe->reflect = NULL;
5934         skinframe->hasalpha = false;
5935
5936         if (ddsbase)
5937         {
5938                 skinframe->base = ddsbase;
5939                 skinframe->hasalpha = ddshasalpha;
5940                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5941                 if (r_loadfog && skinframe->hasalpha)
5942                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
5943                 //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]);
5944         }
5945         else
5946         {
5947                 basepixels_width = image_width;
5948                 basepixels_height = image_height;
5949                 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);
5950                 if (textureflags & TEXF_ALPHA)
5951                 {
5952                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5953                         {
5954                                 if (basepixels[j] < 255)
5955                                 {
5956                                         skinframe->hasalpha = true;
5957                                         break;
5958                                 }
5959                         }
5960                         if (r_loadfog && skinframe->hasalpha)
5961                         {
5962                                 // has transparent pixels
5963                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5964                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5965                                 {
5966                                         pixels[j+0] = 255;
5967                                         pixels[j+1] = 255;
5968                                         pixels[j+2] = 255;
5969                                         pixels[j+3] = basepixels[j+3];
5970                                 }
5971                                 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);
5972                                 Mem_Free(pixels);
5973                         }
5974                 }
5975                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5976                 //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]);
5977                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5978                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
5979                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5980                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
5981         }
5982
5983         if (r_loaddds)
5984         {
5985                 mymiplevel = savemiplevel;
5986                 if (r_loadnormalmap)
5987                         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);
5988                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5989                 if (r_loadgloss)
5990                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5991                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5992                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5993                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5994         }
5995
5996         // _norm is the name used by tenebrae and has been adopted as standard
5997         if (r_loadnormalmap && skinframe->nmap == NULL)
5998         {
5999                 mymiplevel = savemiplevel;
6000                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6001                 {
6002                         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);
6003                         Mem_Free(pixels);
6004                         pixels = NULL;
6005                 }
6006                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6007                 {
6008                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6009                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6010                         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);
6011                         Mem_Free(pixels);
6012                         Mem_Free(bumppixels);
6013                 }
6014                 else if (r_shadow_bumpscale_basetexture.value > 0)
6015                 {
6016                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6017                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6018                         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);
6019                         Mem_Free(pixels);
6020                 }
6021                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6022                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6023         }
6024
6025         // _luma is supported only for tenebrae compatibility
6026         // _glow is the preferred name
6027         mymiplevel = savemiplevel;
6028         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))))
6029         {
6030                 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);
6031                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6032                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6033                 Mem_Free(pixels);pixels = NULL;
6034         }
6035
6036         mymiplevel = savemiplevel;
6037         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6038         {
6039                 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);
6040                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6041                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6042                 Mem_Free(pixels);
6043                 pixels = NULL;
6044         }
6045
6046         mymiplevel = savemiplevel;
6047         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6048         {
6049                 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);
6050                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6051                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6052                 Mem_Free(pixels);
6053                 pixels = NULL;
6054         }
6055
6056         mymiplevel = savemiplevel;
6057         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6058         {
6059                 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);
6060                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6061                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6062                 Mem_Free(pixels);
6063                 pixels = NULL;
6064         }
6065
6066         mymiplevel = savemiplevel;
6067         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6068         {
6069                 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);
6070                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6071                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6072                 Mem_Free(pixels);
6073                 pixels = NULL;
6074         }
6075
6076         if (basepixels)
6077                 Mem_Free(basepixels);
6078
6079         return skinframe;
6080 }
6081
6082 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6083 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6084 {
6085         int i;
6086         unsigned char *temp1, *temp2;
6087         skinframe_t *skinframe;
6088
6089         if (cls.state == ca_dedicated)
6090                 return NULL;
6091
6092         // if already loaded just return it, otherwise make a new skinframe
6093         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6094         if (skinframe && skinframe->base)
6095                 return skinframe;
6096
6097         skinframe->stain = NULL;
6098         skinframe->merged = NULL;
6099         skinframe->base = NULL;
6100         skinframe->pants = NULL;
6101         skinframe->shirt = NULL;
6102         skinframe->nmap = NULL;
6103         skinframe->gloss = NULL;
6104         skinframe->glow = NULL;
6105         skinframe->fog = NULL;
6106         skinframe->reflect = NULL;
6107         skinframe->hasalpha = false;
6108
6109         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6110         if (!skindata)
6111                 return NULL;
6112
6113         if (developer_loading.integer)
6114                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6115
6116         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6117         {
6118                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6119                 temp2 = temp1 + width * height * 4;
6120                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6121                 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);
6122                 Mem_Free(temp1);
6123         }
6124         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6125         if (textureflags & TEXF_ALPHA)
6126         {
6127                 for (i = 3;i < width * height * 4;i += 4)
6128                 {
6129                         if (skindata[i] < 255)
6130                         {
6131                                 skinframe->hasalpha = true;
6132                                 break;
6133                         }
6134                 }
6135                 if (r_loadfog && skinframe->hasalpha)
6136                 {
6137                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6138                         memcpy(fogpixels, skindata, width * height * 4);
6139                         for (i = 0;i < width * height * 4;i += 4)
6140                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6141                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6142                         Mem_Free(fogpixels);
6143                 }
6144         }
6145
6146         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6147         //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]);
6148
6149         return skinframe;
6150 }
6151
6152 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6153 {
6154         int i;
6155         int featuresmask;
6156         skinframe_t *skinframe;
6157
6158         if (cls.state == ca_dedicated)
6159                 return NULL;
6160
6161         // if already loaded just return it, otherwise make a new skinframe
6162         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6163         if (skinframe && skinframe->base)
6164                 return skinframe;
6165
6166         skinframe->stain = NULL;
6167         skinframe->merged = NULL;
6168         skinframe->base = NULL;
6169         skinframe->pants = NULL;
6170         skinframe->shirt = NULL;
6171         skinframe->nmap = NULL;
6172         skinframe->gloss = NULL;
6173         skinframe->glow = NULL;
6174         skinframe->fog = NULL;
6175         skinframe->reflect = NULL;
6176         skinframe->hasalpha = false;
6177
6178         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6179         if (!skindata)
6180                 return NULL;
6181
6182         if (developer_loading.integer)
6183                 Con_Printf("loading quake skin \"%s\"\n", name);
6184
6185         // 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)
6186         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6187         memcpy(skinframe->qpixels, skindata, width*height);
6188         skinframe->qwidth = width;
6189         skinframe->qheight = height;
6190
6191         featuresmask = 0;
6192         for (i = 0;i < width * height;i++)
6193                 featuresmask |= palette_featureflags[skindata[i]];
6194
6195         skinframe->hasalpha = false;
6196         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6197         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6198         skinframe->qgeneratemerged = true;
6199         skinframe->qgeneratebase = skinframe->qhascolormapping;
6200         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6201
6202         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6203         //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]);
6204
6205         return skinframe;
6206 }
6207
6208 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6209 {
6210         int width;
6211         int height;
6212         unsigned char *skindata;
6213
6214         if (!skinframe->qpixels)
6215                 return;
6216
6217         if (!skinframe->qhascolormapping)
6218                 colormapped = false;
6219
6220         if (colormapped)
6221         {
6222                 if (!skinframe->qgeneratebase)
6223                         return;
6224         }
6225         else
6226         {
6227                 if (!skinframe->qgeneratemerged)
6228                         return;
6229         }
6230
6231         width = skinframe->qwidth;
6232         height = skinframe->qheight;
6233         skindata = skinframe->qpixels;
6234
6235         if (skinframe->qgeneratenmap)
6236         {
6237                 unsigned char *temp1, *temp2;
6238                 skinframe->qgeneratenmap = false;
6239                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6240                 temp2 = temp1 + width * height * 4;
6241                 // use either a custom palette or the quake palette
6242                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6243                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6244                 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);
6245                 Mem_Free(temp1);
6246         }
6247
6248         if (skinframe->qgenerateglow)
6249         {
6250                 skinframe->qgenerateglow = false;
6251                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6252         }
6253
6254         if (colormapped)
6255         {
6256                 skinframe->qgeneratebase = false;
6257                 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);
6258                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6259                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6260         }
6261         else
6262         {
6263                 skinframe->qgeneratemerged = false;
6264                 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);
6265         }
6266
6267         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6268         {
6269                 Mem_Free(skinframe->qpixels);
6270                 skinframe->qpixels = NULL;
6271         }
6272 }
6273
6274 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)
6275 {
6276         int i;
6277         skinframe_t *skinframe;
6278
6279         if (cls.state == ca_dedicated)
6280                 return NULL;
6281
6282         // if already loaded just return it, otherwise make a new skinframe
6283         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6284         if (skinframe && skinframe->base)
6285                 return skinframe;
6286
6287         skinframe->stain = NULL;
6288         skinframe->merged = NULL;
6289         skinframe->base = NULL;
6290         skinframe->pants = NULL;
6291         skinframe->shirt = NULL;
6292         skinframe->nmap = NULL;
6293         skinframe->gloss = NULL;
6294         skinframe->glow = NULL;
6295         skinframe->fog = NULL;
6296         skinframe->reflect = NULL;
6297         skinframe->hasalpha = false;
6298
6299         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6300         if (!skindata)
6301                 return NULL;
6302
6303         if (developer_loading.integer)
6304                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6305
6306         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6307         if (textureflags & TEXF_ALPHA)
6308         {
6309                 for (i = 0;i < width * height;i++)
6310                 {
6311                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6312                         {
6313                                 skinframe->hasalpha = true;
6314                                 break;
6315                         }
6316                 }
6317                 if (r_loadfog && skinframe->hasalpha)
6318                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6319         }
6320
6321         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6322         //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]);
6323
6324         return skinframe;
6325 }
6326
6327 skinframe_t *R_SkinFrame_LoadMissing(void)
6328 {
6329         skinframe_t *skinframe;
6330
6331         if (cls.state == ca_dedicated)
6332                 return NULL;
6333
6334         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6335         skinframe->stain = NULL;
6336         skinframe->merged = NULL;
6337         skinframe->base = NULL;
6338         skinframe->pants = NULL;
6339         skinframe->shirt = NULL;
6340         skinframe->nmap = NULL;
6341         skinframe->gloss = NULL;
6342         skinframe->glow = NULL;
6343         skinframe->fog = NULL;
6344         skinframe->reflect = NULL;
6345         skinframe->hasalpha = false;
6346
6347         skinframe->avgcolor[0] = rand() / RAND_MAX;
6348         skinframe->avgcolor[1] = rand() / RAND_MAX;
6349         skinframe->avgcolor[2] = rand() / RAND_MAX;
6350         skinframe->avgcolor[3] = 1;
6351
6352         return skinframe;
6353 }
6354
6355 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6356 typedef struct suffixinfo_s
6357 {
6358         const char *suffix;
6359         qboolean flipx, flipy, flipdiagonal;
6360 }
6361 suffixinfo_t;
6362 static suffixinfo_t suffix[3][6] =
6363 {
6364         {
6365                 {"px",   false, false, false},
6366                 {"nx",   false, false, false},
6367                 {"py",   false, false, false},
6368                 {"ny",   false, false, false},
6369                 {"pz",   false, false, false},
6370                 {"nz",   false, false, false}
6371         },
6372         {
6373                 {"posx", false, false, false},
6374                 {"negx", false, false, false},
6375                 {"posy", false, false, false},
6376                 {"negy", false, false, false},
6377                 {"posz", false, false, false},
6378                 {"negz", false, false, false}
6379         },
6380         {
6381                 {"rt",    true, false,  true},
6382                 {"lf",   false,  true,  true},
6383                 {"ft",    true,  true, false},
6384                 {"bk",   false, false, false},
6385                 {"up",    true, false,  true},
6386                 {"dn",    true, false,  true}
6387         }
6388 };
6389
6390 static int componentorder[4] = {0, 1, 2, 3};
6391
6392 rtexture_t *R_LoadCubemap(const char *basename)
6393 {
6394         int i, j, cubemapsize;
6395         unsigned char *cubemappixels, *image_buffer;
6396         rtexture_t *cubemaptexture;
6397         char name[256];
6398         // must start 0 so the first loadimagepixels has no requested width/height
6399         cubemapsize = 0;
6400         cubemappixels = NULL;
6401         cubemaptexture = NULL;
6402         // keep trying different suffix groups (posx, px, rt) until one loads
6403         for (j = 0;j < 3 && !cubemappixels;j++)
6404         {
6405                 // load the 6 images in the suffix group
6406                 for (i = 0;i < 6;i++)
6407                 {
6408                         // generate an image name based on the base and and suffix
6409                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6410                         // load it
6411                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6412                         {
6413                                 // an image loaded, make sure width and height are equal
6414                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6415                                 {
6416                                         // if this is the first image to load successfully, allocate the cubemap memory
6417                                         if (!cubemappixels && image_width >= 1)
6418                                         {
6419                                                 cubemapsize = image_width;
6420                                                 // note this clears to black, so unavailable sides are black
6421                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6422                                         }
6423                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6424                                         if (cubemappixels)
6425                                                 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);
6426                                 }
6427                                 else
6428                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6429                                 // free the image
6430                                 Mem_Free(image_buffer);
6431                         }
6432                 }
6433         }
6434         // if a cubemap loaded, upload it
6435         if (cubemappixels)
6436         {
6437                 if (developer_loading.integer)
6438                         Con_Printf("loading cubemap \"%s\"\n", basename);
6439
6440                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6441                 Mem_Free(cubemappixels);
6442         }
6443         else
6444         {
6445                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6446                 if (developer_loading.integer)
6447                 {
6448                         Con_Printf("(tried tried images ");
6449                         for (j = 0;j < 3;j++)
6450                                 for (i = 0;i < 6;i++)
6451                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6452                         Con_Print(" and was unable to find any of them).\n");
6453                 }
6454         }
6455         return cubemaptexture;
6456 }
6457
6458 rtexture_t *R_GetCubemap(const char *basename)
6459 {
6460         int i;
6461         for (i = 0;i < r_texture_numcubemaps;i++)
6462                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6463                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6464         if (i >= MAX_CUBEMAPS)
6465                 return r_texture_whitecube;
6466         r_texture_numcubemaps++;
6467         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6468         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6469         return r_texture_cubemaps[i].texture;
6470 }
6471
6472 void R_FreeCubemaps(void)
6473 {
6474         int i;
6475         for (i = 0;i < r_texture_numcubemaps;i++)
6476         {
6477                 if (developer_loading.integer)
6478                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6479                 if (r_texture_cubemaps[i].texture)
6480                         R_FreeTexture(r_texture_cubemaps[i].texture);
6481         }
6482         r_texture_numcubemaps = 0;
6483 }
6484
6485 void R_Main_FreeViewCache(void)
6486 {
6487         if (r_refdef.viewcache.entityvisible)
6488                 Mem_Free(r_refdef.viewcache.entityvisible);
6489         if (r_refdef.viewcache.world_pvsbits)
6490                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6491         if (r_refdef.viewcache.world_leafvisible)
6492                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6493         if (r_refdef.viewcache.world_surfacevisible)
6494                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6495         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6496 }
6497
6498 void R_Main_ResizeViewCache(void)
6499 {
6500         int numentities = r_refdef.scene.numentities;
6501         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6502         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6503         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6504         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6505         if (r_refdef.viewcache.maxentities < numentities)
6506         {
6507                 r_refdef.viewcache.maxentities = numentities;
6508                 if (r_refdef.viewcache.entityvisible)
6509                         Mem_Free(r_refdef.viewcache.entityvisible);
6510                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6511         }
6512         if (r_refdef.viewcache.world_numclusters != numclusters)
6513         {
6514                 r_refdef.viewcache.world_numclusters = numclusters;
6515                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6516                 if (r_refdef.viewcache.world_pvsbits)
6517                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6518                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6519         }
6520         if (r_refdef.viewcache.world_numleafs != numleafs)
6521         {
6522                 r_refdef.viewcache.world_numleafs = numleafs;
6523                 if (r_refdef.viewcache.world_leafvisible)
6524                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6525                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6526         }
6527         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6528         {
6529                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6530                 if (r_refdef.viewcache.world_surfacevisible)
6531                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6532                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6533         }
6534 }
6535
6536 extern rtexture_t *loadingscreentexture;
6537 void gl_main_start(void)
6538 {
6539         loadingscreentexture = NULL;
6540         r_texture_blanknormalmap = NULL;
6541         r_texture_white = NULL;
6542         r_texture_grey128 = NULL;
6543         r_texture_black = NULL;
6544         r_texture_whitecube = NULL;
6545         r_texture_normalizationcube = NULL;
6546         r_texture_fogattenuation = NULL;
6547         r_texture_fogheighttexture = NULL;
6548         r_texture_gammaramps = NULL;
6549         r_texture_numcubemaps = 0;
6550
6551         r_loaddds = r_texture_dds_load.integer != 0;
6552         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6553
6554         switch(vid.renderpath)
6555         {
6556         case RENDERPATH_GL20:
6557         case RENDERPATH_D3D9:
6558         case RENDERPATH_D3D10:
6559         case RENDERPATH_D3D11:
6560         case RENDERPATH_SOFT:
6561                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6562                 Cvar_SetValueQuick(&gl_combine, 1);
6563                 Cvar_SetValueQuick(&r_glsl, 1);
6564                 r_loadnormalmap = true;
6565                 r_loadgloss = true;
6566                 r_loadfog = false;
6567                 break;
6568         case RENDERPATH_GL13:
6569                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6570                 Cvar_SetValueQuick(&gl_combine, 1);
6571                 Cvar_SetValueQuick(&r_glsl, 0);
6572                 r_loadnormalmap = false;
6573                 r_loadgloss = false;
6574                 r_loadfog = true;
6575                 break;
6576         case RENDERPATH_GL11:
6577                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6578                 Cvar_SetValueQuick(&gl_combine, 0);
6579                 Cvar_SetValueQuick(&r_glsl, 0);
6580                 r_loadnormalmap = false;
6581                 r_loadgloss = false;
6582                 r_loadfog = true;
6583                 break;
6584         case RENDERPATH_GLES2:
6585                 Cvar_SetValueQuick(&r_textureunits, 1);
6586                 Cvar_SetValueQuick(&gl_combine, 1);
6587                 Cvar_SetValueQuick(&r_glsl, 1);
6588                 r_loadnormalmap = true;
6589                 r_loadgloss = false;
6590                 r_loadfog = false;
6591                 break;
6592         }
6593
6594         R_AnimCache_Free();
6595         R_FrameData_Reset();
6596
6597         r_numqueries = 0;
6598         r_maxqueries = 0;
6599         memset(r_queries, 0, sizeof(r_queries));
6600
6601         r_qwskincache = NULL;
6602         r_qwskincache_size = 0;
6603
6604         // set up r_skinframe loading system for textures
6605         memset(&r_skinframe, 0, sizeof(r_skinframe));
6606         r_skinframe.loadsequence = 1;
6607         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6608
6609         r_main_texturepool = R_AllocTexturePool();
6610         R_BuildBlankTextures();
6611         R_BuildNoTexture();
6612         if (vid.support.arb_texture_cube_map)
6613         {
6614                 R_BuildWhiteCube();
6615                 R_BuildNormalizationCube();
6616         }
6617         r_texture_fogattenuation = NULL;
6618         r_texture_fogheighttexture = NULL;
6619         r_texture_gammaramps = NULL;
6620         //r_texture_fogintensity = NULL;
6621         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6622         memset(&r_waterstate, 0, sizeof(r_waterstate));
6623         r_glsl_permutation = NULL;
6624         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6625         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6626         glslshaderstring = NULL;
6627 #ifdef SUPPORTD3D
6628         r_hlsl_permutation = NULL;
6629         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6630         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6631 #endif
6632         hlslshaderstring = NULL;
6633         memset(&r_svbsp, 0, sizeof (r_svbsp));
6634
6635         r_refdef.fogmasktable_density = 0;
6636 }
6637
6638 void gl_main_shutdown(void)
6639 {
6640         R_AnimCache_Free();
6641         R_FrameData_Reset();
6642
6643         R_Main_FreeViewCache();
6644
6645         switch(vid.renderpath)
6646         {
6647         case RENDERPATH_GL11:
6648         case RENDERPATH_GL13:
6649         case RENDERPATH_GL20:
6650         case RENDERPATH_GLES2:
6651                 if (r_maxqueries)
6652                         qglDeleteQueriesARB(r_maxqueries, r_queries);
6653                 break;
6654         case RENDERPATH_D3D9:
6655                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6656                 break;
6657         case RENDERPATH_D3D10:
6658                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6659                 break;
6660         case RENDERPATH_D3D11:
6661                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6662                 break;
6663         case RENDERPATH_SOFT:
6664                 break;
6665         }
6666
6667         r_numqueries = 0;
6668         r_maxqueries = 0;
6669         memset(r_queries, 0, sizeof(r_queries));
6670
6671         r_qwskincache = NULL;
6672         r_qwskincache_size = 0;
6673
6674         // clear out the r_skinframe state
6675         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6676         memset(&r_skinframe, 0, sizeof(r_skinframe));
6677
6678         if (r_svbsp.nodes)
6679                 Mem_Free(r_svbsp.nodes);
6680         memset(&r_svbsp, 0, sizeof (r_svbsp));
6681         R_FreeTexturePool(&r_main_texturepool);
6682         loadingscreentexture = NULL;
6683         r_texture_blanknormalmap = NULL;
6684         r_texture_white = NULL;
6685         r_texture_grey128 = NULL;
6686         r_texture_black = NULL;
6687         r_texture_whitecube = NULL;
6688         r_texture_normalizationcube = NULL;
6689         r_texture_fogattenuation = NULL;
6690         r_texture_fogheighttexture = NULL;
6691         r_texture_gammaramps = NULL;
6692         r_texture_numcubemaps = 0;
6693         //r_texture_fogintensity = NULL;
6694         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6695         memset(&r_waterstate, 0, sizeof(r_waterstate));
6696         R_GLSL_Restart_f();
6697
6698         r_glsl_permutation = NULL;
6699         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6700         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
6701         glslshaderstring = NULL;
6702 #ifdef SUPPORTD3D
6703         r_hlsl_permutation = NULL;
6704         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6705         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
6706 #endif
6707         hlslshaderstring = NULL;
6708 }
6709
6710 extern void CL_ParseEntityLump(char *entitystring);
6711 void gl_main_newmap(void)
6712 {
6713         // FIXME: move this code to client
6714         char *entities, entname[MAX_QPATH];
6715         if (r_qwskincache)
6716                 Mem_Free(r_qwskincache);
6717         r_qwskincache = NULL;
6718         r_qwskincache_size = 0;
6719         if (cl.worldmodel)
6720         {
6721                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6722                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6723                 {
6724                         CL_ParseEntityLump(entities);
6725                         Mem_Free(entities);
6726                         return;
6727                 }
6728                 if (cl.worldmodel->brush.entities)
6729                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6730         }
6731         R_Main_FreeViewCache();
6732
6733         R_FrameData_Reset();
6734 }
6735
6736 void GL_Main_Init(void)
6737 {
6738         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6739
6740         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6741         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6742         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6743         if (gamemode == GAME_NEHAHRA)
6744         {
6745                 Cvar_RegisterVariable (&gl_fogenable);
6746                 Cvar_RegisterVariable (&gl_fogdensity);
6747                 Cvar_RegisterVariable (&gl_fogred);
6748                 Cvar_RegisterVariable (&gl_foggreen);
6749                 Cvar_RegisterVariable (&gl_fogblue);
6750                 Cvar_RegisterVariable (&gl_fogstart);
6751                 Cvar_RegisterVariable (&gl_fogend);
6752                 Cvar_RegisterVariable (&gl_skyclip);
6753         }
6754         Cvar_RegisterVariable(&r_motionblur);
6755         Cvar_RegisterVariable(&r_motionblur_maxblur);
6756         Cvar_RegisterVariable(&r_motionblur_bmin);
6757         Cvar_RegisterVariable(&r_motionblur_vmin);
6758         Cvar_RegisterVariable(&r_motionblur_vmax);
6759         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6760         Cvar_RegisterVariable(&r_motionblur_randomize);
6761         Cvar_RegisterVariable(&r_damageblur);
6762         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6763         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6764         Cvar_RegisterVariable(&r_equalize_entities_by);
6765         Cvar_RegisterVariable(&r_equalize_entities_to);
6766         Cvar_RegisterVariable(&r_depthfirst);
6767         Cvar_RegisterVariable(&r_useinfinitefarclip);
6768         Cvar_RegisterVariable(&r_farclip_base);
6769         Cvar_RegisterVariable(&r_farclip_world);
6770         Cvar_RegisterVariable(&r_nearclip);
6771         Cvar_RegisterVariable(&r_showbboxes);
6772         Cvar_RegisterVariable(&r_showsurfaces);
6773         Cvar_RegisterVariable(&r_showtris);
6774         Cvar_RegisterVariable(&r_shownormals);
6775         Cvar_RegisterVariable(&r_showlighting);
6776         Cvar_RegisterVariable(&r_showshadowvolumes);
6777         Cvar_RegisterVariable(&r_showcollisionbrushes);
6778         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6779         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6780         Cvar_RegisterVariable(&r_showdisabledepthtest);
6781         Cvar_RegisterVariable(&r_drawportals);
6782         Cvar_RegisterVariable(&r_drawentities);
6783         Cvar_RegisterVariable(&r_draw2d);
6784         Cvar_RegisterVariable(&r_drawworld);
6785         Cvar_RegisterVariable(&r_cullentities_trace);
6786         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6787         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6788         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6789         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6790         Cvar_RegisterVariable(&r_drawviewmodel);
6791         Cvar_RegisterVariable(&r_drawexteriormodel);
6792         Cvar_RegisterVariable(&r_speeds);
6793         Cvar_RegisterVariable(&r_fullbrights);
6794         Cvar_RegisterVariable(&r_wateralpha);
6795         Cvar_RegisterVariable(&r_dynamic);
6796         Cvar_RegisterVariable(&r_fakelight);
6797         Cvar_RegisterVariable(&r_fakelight_intensity);
6798         Cvar_RegisterVariable(&r_fullbright);
6799         Cvar_RegisterVariable(&r_shadows);
6800         Cvar_RegisterVariable(&r_shadows_darken);
6801         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6802         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6803         Cvar_RegisterVariable(&r_shadows_throwdistance);
6804         Cvar_RegisterVariable(&r_shadows_throwdirection);
6805         Cvar_RegisterVariable(&r_shadows_focus);
6806         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6807         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6808         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6809         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6810         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6811         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6812         Cvar_RegisterVariable(&r_fog_exp2);
6813         Cvar_RegisterVariable(&r_drawfog);
6814         Cvar_RegisterVariable(&r_transparentdepthmasking);
6815         Cvar_RegisterVariable(&r_texture_dds_load);
6816         Cvar_RegisterVariable(&r_texture_dds_save);
6817         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6818         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6819         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6820         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6821         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6822         Cvar_RegisterVariable(&r_textureunits);
6823         Cvar_RegisterVariable(&gl_combine);
6824         Cvar_RegisterVariable(&r_glsl);
6825         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6826         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6827         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6828         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6829         Cvar_RegisterVariable(&r_glsl_postprocess);
6830         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6831         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6832         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6833         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6834         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6835         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6836         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6837         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6838
6839         Cvar_RegisterVariable(&r_water);
6840         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6841         Cvar_RegisterVariable(&r_water_clippingplanebias);
6842         Cvar_RegisterVariable(&r_water_refractdistort);
6843         Cvar_RegisterVariable(&r_water_reflectdistort);
6844         Cvar_RegisterVariable(&r_water_scissormode);
6845         Cvar_RegisterVariable(&r_lerpsprites);
6846         Cvar_RegisterVariable(&r_lerpmodels);
6847         Cvar_RegisterVariable(&r_lerplightstyles);
6848         Cvar_RegisterVariable(&r_waterscroll);
6849         Cvar_RegisterVariable(&r_bloom);
6850         Cvar_RegisterVariable(&r_bloom_colorscale);
6851         Cvar_RegisterVariable(&r_bloom_brighten);
6852         Cvar_RegisterVariable(&r_bloom_blur);
6853         Cvar_RegisterVariable(&r_bloom_resolution);
6854         Cvar_RegisterVariable(&r_bloom_colorexponent);
6855         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6856         Cvar_RegisterVariable(&r_hdr);
6857         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6858         Cvar_RegisterVariable(&r_hdr_glowintensity);
6859         Cvar_RegisterVariable(&r_hdr_range);
6860         Cvar_RegisterVariable(&r_hdr_irisadaptation);
6861         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
6862         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
6863         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
6864         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
6865         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
6866         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6867         Cvar_RegisterVariable(&developer_texturelogging);
6868         Cvar_RegisterVariable(&gl_lightmaps);
6869         Cvar_RegisterVariable(&r_test);
6870         Cvar_RegisterVariable(&r_glsl_saturation);
6871         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6872         Cvar_RegisterVariable(&r_framedatasize);
6873         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6874                 Cvar_SetValue("r_fullbrights", 0);
6875         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6876
6877         Cvar_RegisterVariable(&r_track_sprites);
6878         Cvar_RegisterVariable(&r_track_sprites_flags);
6879         Cvar_RegisterVariable(&r_track_sprites_scalew);
6880         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6881         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6882         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6883         Cvar_RegisterVariable(&r_overheadsprites_scalex);
6884         Cvar_RegisterVariable(&r_overheadsprites_scaley);
6885 }
6886
6887 extern void R_Textures_Init(void);
6888 extern void GL_Draw_Init(void);
6889 extern void GL_Main_Init(void);
6890 extern void R_Shadow_Init(void);
6891 extern void R_Sky_Init(void);
6892 extern void GL_Surf_Init(void);
6893 extern void R_Particles_Init(void);
6894 extern void R_Explosion_Init(void);
6895 extern void gl_backend_init(void);
6896 extern void Sbar_Init(void);
6897 extern void R_LightningBeams_Init(void);
6898 extern void Mod_RenderInit(void);
6899 extern void Font_Init(void);
6900
6901 void Render_Init(void)
6902 {
6903         gl_backend_init();
6904         R_Textures_Init();
6905         GL_Main_Init();
6906         Font_Init();
6907         GL_Draw_Init();
6908         R_Shadow_Init();
6909         R_Sky_Init();
6910         GL_Surf_Init();
6911         Sbar_Init();
6912         R_Particles_Init();
6913         R_Explosion_Init();
6914         R_LightningBeams_Init();
6915         Mod_RenderInit();
6916 }
6917
6918 /*
6919 ===============
6920 GL_Init
6921 ===============
6922 */
6923 extern char *ENGINE_EXTENSIONS;
6924 void GL_Init (void)
6925 {
6926         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6927         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6928         gl_version = (const char *)qglGetString(GL_VERSION);
6929         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6930
6931         if (!gl_extensions)
6932                 gl_extensions = "";
6933         if (!gl_platformextensions)
6934                 gl_platformextensions = "";
6935
6936         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6937         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6938         Con_Printf("GL_VERSION: %s\n", gl_version);
6939         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6940         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6941
6942         VID_CheckExtensions();
6943
6944         // LordHavoc: report supported extensions
6945         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6946
6947         // clear to black (loading plaque will be seen over this)
6948         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6949 }
6950
6951 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6952 {
6953         int i;
6954         mplane_t *p;
6955         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6956         {
6957                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6958                 if (i == 4)
6959                         continue;
6960                 p = r_refdef.view.frustum + i;
6961                 switch(p->signbits)
6962                 {
6963                 default:
6964                 case 0:
6965                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6966                                 return true;
6967                         break;
6968                 case 1:
6969                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6970                                 return true;
6971                         break;
6972                 case 2:
6973                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6974                                 return true;
6975                         break;
6976                 case 3:
6977                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6978                                 return true;
6979                         break;
6980                 case 4:
6981                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6982                                 return true;
6983                         break;
6984                 case 5:
6985                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6986                                 return true;
6987                         break;
6988                 case 6:
6989                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6990                                 return true;
6991                         break;
6992                 case 7:
6993                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6994                                 return true;
6995                         break;
6996                 }
6997         }
6998         return false;
6999 }
7000
7001 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7002 {
7003         int i;
7004         const mplane_t *p;
7005         for (i = 0;i < numplanes;i++)
7006         {
7007                 p = planes + i;
7008                 switch(p->signbits)
7009                 {
7010                 default:
7011                 case 0:
7012                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7013                                 return true;
7014                         break;
7015                 case 1:
7016                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7017                                 return true;
7018                         break;
7019                 case 2:
7020                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7021                                 return true;
7022                         break;
7023                 case 3:
7024                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7025                                 return true;
7026                         break;
7027                 case 4:
7028                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7029                                 return true;
7030                         break;
7031                 case 5:
7032                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7033                                 return true;
7034                         break;
7035                 case 6:
7036                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7037                                 return true;
7038                         break;
7039                 case 7:
7040                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7041                                 return true;
7042                         break;
7043                 }
7044         }
7045         return false;
7046 }
7047
7048 //==================================================================================
7049
7050 // LordHavoc: this stores temporary data used within the same frame
7051
7052 typedef struct r_framedata_mem_s
7053 {
7054         struct r_framedata_mem_s *purge; // older mem block to free on next frame
7055         size_t size; // how much usable space
7056         size_t current; // how much space in use
7057         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7058         size_t wantedsize; // how much space was allocated
7059         unsigned char *data; // start of real data (16byte aligned)
7060 }
7061 r_framedata_mem_t;
7062
7063 static r_framedata_mem_t *r_framedata_mem;
7064
7065 void R_FrameData_Reset(void)
7066 {
7067         while (r_framedata_mem)
7068         {
7069                 r_framedata_mem_t *next = r_framedata_mem->purge;
7070                 Mem_Free(r_framedata_mem);
7071                 r_framedata_mem = next;
7072         }
7073 }
7074
7075 void R_FrameData_Resize(void)
7076 {
7077         size_t wantedsize;
7078         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7079         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7080         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7081         {
7082                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7083                 newmem->wantedsize = wantedsize;
7084                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7085                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7086                 newmem->current = 0;
7087                 newmem->mark = 0;
7088                 newmem->purge = r_framedata_mem;
7089                 r_framedata_mem = newmem;
7090         }
7091 }
7092
7093 void R_FrameData_NewFrame(void)
7094 {
7095         R_FrameData_Resize();
7096         if (!r_framedata_mem)
7097                 return;
7098         // if we ran out of space on the last frame, free the old memory now
7099         while (r_framedata_mem->purge)
7100         {
7101                 // repeatedly remove the second item in the list, leaving only head
7102                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7103                 Mem_Free(r_framedata_mem->purge);
7104                 r_framedata_mem->purge = next;
7105         }
7106         // reset the current mem pointer
7107         r_framedata_mem->current = 0;
7108         r_framedata_mem->mark = 0;
7109 }
7110
7111 void *R_FrameData_Alloc(size_t size)
7112 {
7113         void *data;
7114
7115         // align to 16 byte boundary - the data pointer is already aligned, so we
7116         // only need to ensure the size of every allocation is also aligned
7117         size = (size + 15) & ~15;
7118
7119         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7120         {
7121                 // emergency - we ran out of space, allocate more memory
7122                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7123                 R_FrameData_Resize();
7124         }
7125
7126         data = r_framedata_mem->data + r_framedata_mem->current;
7127         r_framedata_mem->current += size;
7128
7129         // count the usage for stats
7130         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7131         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7132
7133         return (void *)data;
7134 }
7135
7136 void *R_FrameData_Store(size_t size, void *data)
7137 {
7138         void *d = R_FrameData_Alloc(size);
7139         if (d && data)
7140                 memcpy(d, data, size);
7141         return d;
7142 }
7143
7144 void R_FrameData_SetMark(void)
7145 {
7146         if (!r_framedata_mem)
7147                 return;
7148         r_framedata_mem->mark = r_framedata_mem->current;
7149 }
7150
7151 void R_FrameData_ReturnToMark(void)
7152 {
7153         if (!r_framedata_mem)
7154                 return;
7155         r_framedata_mem->current = r_framedata_mem->mark;
7156 }
7157
7158 //==================================================================================
7159
7160 // LordHavoc: animcache originally written by Echon, rewritten since then
7161
7162 /**
7163  * Animation cache prevents re-generating mesh data for an animated model
7164  * multiple times in one frame for lighting, shadowing, reflections, etc.
7165  */
7166
7167 void R_AnimCache_Free(void)
7168 {
7169 }
7170
7171 void R_AnimCache_ClearCache(void)
7172 {
7173         int i;
7174         entity_render_t *ent;
7175
7176         for (i = 0;i < r_refdef.scene.numentities;i++)
7177         {
7178                 ent = r_refdef.scene.entities[i];
7179                 ent->animcache_vertex3f = NULL;
7180                 ent->animcache_normal3f = NULL;
7181                 ent->animcache_svector3f = NULL;
7182                 ent->animcache_tvector3f = NULL;
7183                 ent->animcache_vertexmesh = NULL;
7184                 ent->animcache_vertex3fbuffer = NULL;
7185                 ent->animcache_vertexmeshbuffer = NULL;
7186         }
7187 }
7188
7189 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7190 {
7191         int i;
7192
7193         // check if we need the meshbuffers
7194         if (!vid.useinterleavedarrays)
7195                 return;
7196
7197         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7198                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7199         // TODO: upload vertex3f buffer?
7200         if (ent->animcache_vertexmesh)
7201         {
7202                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7203                 for (i = 0;i < numvertices;i++)
7204                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7205                 if (ent->animcache_svector3f)
7206                         for (i = 0;i < numvertices;i++)
7207                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7208                 if (ent->animcache_tvector3f)
7209                         for (i = 0;i < numvertices;i++)
7210                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7211                 if (ent->animcache_normal3f)
7212                         for (i = 0;i < numvertices;i++)
7213                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7214                 // TODO: upload vertexmeshbuffer?
7215         }
7216 }
7217
7218 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7219 {
7220         dp_model_t *model = ent->model;
7221         int numvertices;
7222         // see if it's already cached this frame
7223         if (ent->animcache_vertex3f)
7224         {
7225                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7226                 if (wantnormals || wanttangents)
7227                 {
7228                         if (ent->animcache_normal3f)
7229                                 wantnormals = false;
7230                         if (ent->animcache_svector3f)
7231                                 wanttangents = false;
7232                         if (wantnormals || wanttangents)
7233                         {
7234                                 numvertices = model->surfmesh.num_vertices;
7235                                 if (wantnormals)
7236                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7237                                 if (wanttangents)
7238                                 {
7239                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7240                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7241                                 }
7242                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7243                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7244                         }
7245                 }
7246         }
7247         else
7248         {
7249                 // see if this ent is worth caching
7250                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7251                         return false;
7252                 // get some memory for this entity and generate mesh data
7253                 numvertices = model->surfmesh.num_vertices;
7254                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7255                 if (wantnormals)
7256                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7257                 if (wanttangents)
7258                 {
7259                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7260                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7261                 }
7262                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7263                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7264         }
7265         return true;
7266 }
7267
7268 void R_AnimCache_CacheVisibleEntities(void)
7269 {
7270         int i;
7271         qboolean wantnormals = true;
7272         qboolean wanttangents = !r_showsurfaces.integer;
7273
7274         switch(vid.renderpath)
7275         {
7276         case RENDERPATH_GL20:
7277         case RENDERPATH_D3D9:
7278         case RENDERPATH_D3D10:
7279         case RENDERPATH_D3D11:
7280         case RENDERPATH_GLES2:
7281                 break;
7282         case RENDERPATH_GL13:
7283         case RENDERPATH_GL11:
7284                 wanttangents = false;
7285                 break;
7286         case RENDERPATH_SOFT:
7287                 break;
7288         }
7289
7290         if (r_shownormals.integer)
7291                 wanttangents = wantnormals = true;
7292
7293         // TODO: thread this
7294         // NOTE: R_PrepareRTLights() also caches entities
7295
7296         for (i = 0;i < r_refdef.scene.numentities;i++)
7297                 if (r_refdef.viewcache.entityvisible[i])
7298                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7299 }
7300
7301 //==================================================================================
7302
7303 static void R_View_UpdateEntityLighting (void)
7304 {
7305         int i;
7306         entity_render_t *ent;
7307         vec3_t tempdiffusenormal, avg;
7308         vec_t f, fa, fd, fdd;
7309         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7310
7311         for (i = 0;i < r_refdef.scene.numentities;i++)
7312         {
7313                 ent = r_refdef.scene.entities[i];
7314
7315                 // skip unseen models
7316                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7317                         continue;
7318
7319                 // skip bsp models
7320                 if (ent->model && ent->model->brush.num_leafs)
7321                 {
7322                         // TODO: use modellight for r_ambient settings on world?
7323                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7324                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7325                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7326                         continue;
7327                 }
7328
7329                 // fetch the lighting from the worldmodel data
7330                 VectorClear(ent->modellight_ambient);
7331                 VectorClear(ent->modellight_diffuse);
7332                 VectorClear(tempdiffusenormal);
7333                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7334                 {
7335                         vec3_t org;
7336                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7337
7338                         // complete lightning for lit sprites
7339                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7340                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7341                         {
7342                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7343                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7344                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7345                         }
7346                         else
7347                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
7348
7349                         if(ent->flags & RENDER_EQUALIZE)
7350                         {
7351                                 // first fix up ambient lighting...
7352                                 if(r_equalize_entities_minambient.value > 0)
7353                                 {
7354                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7355                                         if(fd > 0)
7356                                         {
7357                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7358                                                 if(fa < r_equalize_entities_minambient.value * fd)
7359                                                 {
7360                                                         // solve:
7361                                                         //   fa'/fd' = minambient
7362                                                         //   fa'+0.25*fd' = fa+0.25*fd
7363                                                         //   ...
7364                                                         //   fa' = fd' * minambient
7365                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7366                                                         //   ...
7367                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7368                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7369                                                         //   ...
7370                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7371                                                         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
7372                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7373                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7374                                                 }
7375                                         }
7376                                 }
7377
7378                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7379                                 {
7380                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7381                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7382                                         f = fa + 0.25 * fd;
7383                                         if(f > 0)
7384                                         {
7385                                                 // adjust brightness and saturation to target
7386                                                 avg[0] = avg[1] = avg[2] = fa / f;
7387                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7388                                                 avg[0] = avg[1] = avg[2] = fd / f;
7389                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7390                                         }
7391                                 }
7392                         }
7393                 }
7394                 else // highly rare
7395                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7396
7397                 // move the light direction into modelspace coordinates for lighting code
7398                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7399                 if(VectorLength2(ent->modellight_lightdir) == 0)
7400                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7401                 VectorNormalize(ent->modellight_lightdir);
7402         }
7403 }
7404
7405 #define MAX_LINEOFSIGHTTRACES 64
7406
7407 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7408 {
7409         int i;
7410         vec3_t boxmins, boxmaxs;
7411         vec3_t start;
7412         vec3_t end;
7413         dp_model_t *model = r_refdef.scene.worldmodel;
7414
7415         if (!model || !model->brush.TraceLineOfSight)
7416                 return true;
7417
7418         // expand the box a little
7419         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7420         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7421         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7422         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7423         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7424         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7425
7426         // return true if eye is inside enlarged box
7427         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7428                 return true;
7429
7430         // try center
7431         VectorCopy(eye, start);
7432         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7433         if (model->brush.TraceLineOfSight(model, start, end))
7434                 return true;
7435
7436         // try various random positions
7437         for (i = 0;i < numsamples;i++)
7438         {
7439                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7440                 if (model->brush.TraceLineOfSight(model, start, end))
7441                         return true;
7442         }
7443
7444         return false;
7445 }
7446
7447
7448 static void R_View_UpdateEntityVisible (void)
7449 {
7450         int i;
7451         int renderimask;
7452         int samples;
7453         entity_render_t *ent;
7454
7455         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7456                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7457                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7458                 :                                                          RENDER_EXTERIORMODEL;
7459         if (!r_drawviewmodel.integer)
7460                 renderimask |= RENDER_VIEWMODEL;
7461         if (!r_drawexteriormodel.integer)
7462                 renderimask |= RENDER_EXTERIORMODEL;
7463         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7464         {
7465                 // worldmodel can check visibility
7466                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7467                 for (i = 0;i < r_refdef.scene.numentities;i++)
7468                 {
7469                         ent = r_refdef.scene.entities[i];
7470                         if (!(ent->flags & renderimask))
7471                         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)))
7472                         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))
7473                                 r_refdef.viewcache.entityvisible[i] = true;
7474                 }
7475                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7476                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7477                 {
7478                         for (i = 0;i < r_refdef.scene.numentities;i++)
7479                         {
7480                                 ent = r_refdef.scene.entities[i];
7481                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7482                                 {
7483                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7484                                         if (samples < 0)
7485                                                 continue; // temp entities do pvs only
7486                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7487                                                 ent->last_trace_visibility = realtime;
7488                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7489                                                 r_refdef.viewcache.entityvisible[i] = 0;
7490                                 }
7491                         }
7492                 }
7493         }
7494         else
7495         {
7496                 // no worldmodel or it can't check visibility
7497                 for (i = 0;i < r_refdef.scene.numentities;i++)
7498                 {
7499                         ent = r_refdef.scene.entities[i];
7500                         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));
7501                 }
7502         }
7503 }
7504
7505 /// only used if skyrendermasked, and normally returns false
7506 int R_DrawBrushModelsSky (void)
7507 {
7508         int i, sky;
7509         entity_render_t *ent;
7510
7511         sky = false;
7512         for (i = 0;i < r_refdef.scene.numentities;i++)
7513         {
7514                 if (!r_refdef.viewcache.entityvisible[i])
7515                         continue;
7516                 ent = r_refdef.scene.entities[i];
7517                 if (!ent->model || !ent->model->DrawSky)
7518                         continue;
7519                 ent->model->DrawSky(ent);
7520                 sky = true;
7521         }
7522         return sky;
7523 }
7524
7525 static void R_DrawNoModel(entity_render_t *ent);
7526 static void R_DrawModels(void)
7527 {
7528         int i;
7529         entity_render_t *ent;
7530
7531         for (i = 0;i < r_refdef.scene.numentities;i++)
7532         {
7533                 if (!r_refdef.viewcache.entityvisible[i])
7534                         continue;
7535                 ent = r_refdef.scene.entities[i];
7536                 r_refdef.stats.entities++;
7537                 if (ent->model && ent->model->Draw != NULL)
7538                         ent->model->Draw(ent);
7539                 else
7540                         R_DrawNoModel(ent);
7541         }
7542 }
7543
7544 static void R_DrawModelsDepth(void)
7545 {
7546         int i;
7547         entity_render_t *ent;
7548
7549         for (i = 0;i < r_refdef.scene.numentities;i++)
7550         {
7551                 if (!r_refdef.viewcache.entityvisible[i])
7552                         continue;
7553                 ent = r_refdef.scene.entities[i];
7554                 if (ent->model && ent->model->DrawDepth != NULL)
7555                         ent->model->DrawDepth(ent);
7556         }
7557 }
7558
7559 static void R_DrawModelsDebug(void)
7560 {
7561         int i;
7562         entity_render_t *ent;
7563
7564         for (i = 0;i < r_refdef.scene.numentities;i++)
7565         {
7566                 if (!r_refdef.viewcache.entityvisible[i])
7567                         continue;
7568                 ent = r_refdef.scene.entities[i];
7569                 if (ent->model && ent->model->DrawDebug != NULL)
7570                         ent->model->DrawDebug(ent);
7571         }
7572 }
7573
7574 static void R_DrawModelsAddWaterPlanes(void)
7575 {
7576         int i;
7577         entity_render_t *ent;
7578
7579         for (i = 0;i < r_refdef.scene.numentities;i++)
7580         {
7581                 if (!r_refdef.viewcache.entityvisible[i])
7582                         continue;
7583                 ent = r_refdef.scene.entities[i];
7584                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7585                         ent->model->DrawAddWaterPlanes(ent);
7586         }
7587 }
7588
7589 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
7590 {
7591         if (r_hdr_irisadaptation.integer)
7592         {
7593                 vec3_t ambient;
7594                 vec3_t diffuse;
7595                 vec3_t diffusenormal;
7596                 vec_t brightness;
7597                 vec_t goal;
7598                 vec_t adjust;
7599                 vec_t current;
7600                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7601                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
7602                 brightness = max(0.0000001f, brightness);
7603                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
7604                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
7605                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
7606                 current = r_hdr_irisadaptation_value.value;
7607                 if (current < goal)
7608                         current = min(current + adjust, goal);
7609                 else if (current > goal)
7610                         current = max(current - adjust, goal);
7611                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
7612                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
7613         }
7614         else if (r_hdr_irisadaptation_value.value != 1.0f)
7615                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
7616 }
7617
7618 static void R_View_SetFrustum(const int *scissor)
7619 {
7620         int i;
7621         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7622         vec3_t forward, left, up, origin, v;
7623
7624         if(scissor)
7625         {
7626                 // flipped x coordinates (because x points left here)
7627                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7628                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7629
7630                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
7631                 switch(vid.renderpath)
7632                 {
7633                         case RENDERPATH_D3D9:
7634                         case RENDERPATH_D3D10:
7635                         case RENDERPATH_D3D11:
7636                         case RENDERPATH_SOFT:
7637                                 // non-flipped y coordinates
7638                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7639                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7640                                 break;
7641                         case RENDERPATH_GL11:
7642                         case RENDERPATH_GL13:
7643                         case RENDERPATH_GL20:
7644                         case RENDERPATH_GLES2:
7645                                 // non-flipped y coordinates
7646                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7647                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7648                                 break;
7649                 }
7650         }
7651
7652         // we can't trust r_refdef.view.forward and friends in reflected scenes
7653         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7654
7655 #if 0
7656         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7657         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7658         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7659         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7660         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7661         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7662         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7663         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7664         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7665         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7666         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7667         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7668 #endif
7669
7670 #if 0
7671         zNear = r_refdef.nearclip;
7672         nudge = 1.0 - 1.0 / (1<<23);
7673         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7674         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7675         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7676         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7677         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7678         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7679         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7680         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7681 #endif
7682
7683
7684
7685 #if 0
7686         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7687         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7688         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7689         r_refdef.view.frustum[0].dist = m[15] - m[12];
7690
7691         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7692         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7693         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7694         r_refdef.view.frustum[1].dist = m[15] + m[12];
7695
7696         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7697         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7698         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7699         r_refdef.view.frustum[2].dist = m[15] - m[13];
7700
7701         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7702         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7703         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7704         r_refdef.view.frustum[3].dist = m[15] + m[13];
7705
7706         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7707         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7708         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7709         r_refdef.view.frustum[4].dist = m[15] - m[14];
7710
7711         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7712         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7713         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7714         r_refdef.view.frustum[5].dist = m[15] + m[14];
7715 #endif
7716
7717         if (r_refdef.view.useperspective)
7718         {
7719                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7720                 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]);
7721                 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]);
7722                 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]);
7723                 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]);
7724
7725                 // then the normals from the corners relative to origin
7726                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7727                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7728                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7729                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7730
7731                 // in a NORMAL view, forward cross left == up
7732                 // in a REFLECTED view, forward cross left == down
7733                 // so our cross products above need to be adjusted for a left handed coordinate system
7734                 CrossProduct(forward, left, v);
7735                 if(DotProduct(v, up) < 0)
7736                 {
7737                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7738                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7739                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7740                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7741                 }
7742
7743                 // Leaving those out was a mistake, those were in the old code, and they
7744                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7745                 // I couldn't reproduce it after adding those normalizations. --blub
7746                 VectorNormalize(r_refdef.view.frustum[0].normal);
7747                 VectorNormalize(r_refdef.view.frustum[1].normal);
7748                 VectorNormalize(r_refdef.view.frustum[2].normal);
7749                 VectorNormalize(r_refdef.view.frustum[3].normal);
7750
7751                 // make the corners absolute
7752                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7753                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7754                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7755                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7756
7757                 // one more normal
7758                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7759
7760                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7761                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7762                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7763                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7764                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7765         }
7766         else
7767         {
7768                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7769                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7770                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7771                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7772                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7773                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7774                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7775                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7776                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7777                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7778         }
7779         r_refdef.view.numfrustumplanes = 5;
7780
7781         if (r_refdef.view.useclipplane)
7782         {
7783                 r_refdef.view.numfrustumplanes = 6;
7784                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7785         }
7786
7787         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7788                 PlaneClassify(r_refdef.view.frustum + i);
7789
7790         // LordHavoc: note to all quake engine coders, Quake had a special case
7791         // for 90 degrees which assumed a square view (wrong), so I removed it,
7792         // Quake2 has it disabled as well.
7793
7794         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7795         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7796         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7797         //PlaneClassify(&frustum[0]);
7798
7799         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7800         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7801         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7802         //PlaneClassify(&frustum[1]);
7803
7804         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7805         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7806         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7807         //PlaneClassify(&frustum[2]);
7808
7809         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7810         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7811         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7812         //PlaneClassify(&frustum[3]);
7813
7814         // nearclip plane
7815         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7816         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7817         //PlaneClassify(&frustum[4]);
7818 }
7819
7820 void R_View_UpdateWithScissor(const int *myscissor)
7821 {
7822         R_Main_ResizeViewCache();
7823         R_View_SetFrustum(myscissor);
7824         R_View_WorldVisibility(r_refdef.view.useclipplane);
7825         R_View_UpdateEntityVisible();
7826         R_View_UpdateEntityLighting();
7827 }
7828
7829 void R_View_Update(void)
7830 {
7831         R_Main_ResizeViewCache();
7832         R_View_SetFrustum(NULL);
7833         R_View_WorldVisibility(r_refdef.view.useclipplane);
7834         R_View_UpdateEntityVisible();
7835         R_View_UpdateEntityLighting();
7836 }
7837
7838 void R_SetupView(qboolean allowwaterclippingplane)
7839 {
7840         const float *customclipplane = NULL;
7841         float plane[4];
7842         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7843         {
7844                 // LordHavoc: couldn't figure out how to make this approach the
7845                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7846                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7847                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7848                         dist = r_refdef.view.clipplane.dist;
7849                 plane[0] = r_refdef.view.clipplane.normal[0];
7850                 plane[1] = r_refdef.view.clipplane.normal[1];
7851                 plane[2] = r_refdef.view.clipplane.normal[2];
7852                 plane[3] = dist;
7853                 customclipplane = plane;
7854         }
7855
7856         if (!r_refdef.view.useperspective)
7857                 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);
7858         else if (vid.stencil && r_useinfinitefarclip.integer)
7859                 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);
7860         else
7861                 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);
7862         R_SetViewport(&r_refdef.view.viewport);
7863 }
7864
7865 void R_EntityMatrix(const matrix4x4_t *matrix)
7866 {
7867         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7868         {
7869                 gl_modelmatrixchanged = false;
7870                 gl_modelmatrix = *matrix;
7871                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7872                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7873                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7874                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7875                 CHECKGLERROR
7876                 switch(vid.renderpath)
7877                 {
7878                 case RENDERPATH_D3D9:
7879 #ifdef SUPPORTD3D
7880                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
7881                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
7882 #endif
7883                         break;
7884                 case RENDERPATH_D3D10:
7885                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
7886                         break;
7887                 case RENDERPATH_D3D11:
7888                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
7889                         break;
7890                 case RENDERPATH_GL13:
7891                 case RENDERPATH_GL11:
7892                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7893                         break;
7894                 case RENDERPATH_SOFT:
7895                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
7896                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
7897                         break;
7898                 case RENDERPATH_GL20:
7899                 case RENDERPATH_GLES2:
7900                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7901                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7902                         break;
7903                 }
7904         }
7905 }
7906
7907 void R_ResetViewRendering2D(void)
7908 {
7909         r_viewport_t viewport;
7910         DrawQ_Finish();
7911
7912         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7913         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);
7914         R_SetViewport(&viewport);
7915         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7916         GL_Color(1, 1, 1, 1);
7917         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7918         GL_BlendFunc(GL_ONE, GL_ZERO);
7919         GL_ScissorTest(false);
7920         GL_DepthMask(false);
7921         GL_DepthRange(0, 1);
7922         GL_DepthTest(false);
7923         GL_DepthFunc(GL_LEQUAL);
7924         R_EntityMatrix(&identitymatrix);
7925         R_Mesh_ResetTextureState();
7926         GL_PolygonOffset(0, 0);
7927         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7928         switch(vid.renderpath)
7929         {
7930         case RENDERPATH_GL11:
7931         case RENDERPATH_GL13:
7932         case RENDERPATH_GL20:
7933         case RENDERPATH_GLES2:
7934                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7935                 break;
7936         case RENDERPATH_D3D9:
7937         case RENDERPATH_D3D10:
7938         case RENDERPATH_D3D11:
7939         case RENDERPATH_SOFT:
7940                 break;
7941         }
7942         GL_CullFace(GL_NONE);
7943 }
7944
7945 void R_ResetViewRendering3D(void)
7946 {
7947         DrawQ_Finish();
7948
7949         R_SetupView(true);
7950         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7951         GL_Color(1, 1, 1, 1);
7952         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7953         GL_BlendFunc(GL_ONE, GL_ZERO);
7954         GL_ScissorTest(true);
7955         GL_DepthMask(true);
7956         GL_DepthRange(0, 1);
7957         GL_DepthTest(true);
7958         GL_DepthFunc(GL_LEQUAL);
7959         R_EntityMatrix(&identitymatrix);
7960         R_Mesh_ResetTextureState();
7961         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7962         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7963         switch(vid.renderpath)
7964         {
7965         case RENDERPATH_GL11:
7966         case RENDERPATH_GL13:
7967         case RENDERPATH_GL20:
7968         case RENDERPATH_GLES2:
7969                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7970                 break;
7971         case RENDERPATH_D3D9:
7972         case RENDERPATH_D3D10:
7973         case RENDERPATH_D3D11:
7974         case RENDERPATH_SOFT:
7975                 break;
7976         }
7977         GL_CullFace(r_refdef.view.cullface_back);
7978 }
7979
7980 /*
7981 ================
7982 R_RenderView_UpdateViewVectors
7983 ================
7984 */
7985 static void R_RenderView_UpdateViewVectors(void)
7986 {
7987         // break apart the view matrix into vectors for various purposes
7988         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7989         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7990         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7991         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7992         // make an inverted copy of the view matrix for tracking sprites
7993         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7994 }
7995
7996 void R_RenderScene(void);
7997 void R_RenderWaterPlanes(void);
7998
7999 static void R_Water_StartFrame(void)
8000 {
8001         int i;
8002         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8003         r_waterstate_waterplane_t *p;
8004
8005         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8006                 return;
8007
8008         switch(vid.renderpath)
8009         {
8010         case RENDERPATH_GL20:
8011         case RENDERPATH_D3D9:
8012         case RENDERPATH_D3D10:
8013         case RENDERPATH_D3D11:
8014         case RENDERPATH_SOFT:
8015         case RENDERPATH_GLES2:
8016                 break;
8017         case RENDERPATH_GL13:
8018         case RENDERPATH_GL11:
8019                 return;
8020         }
8021
8022         // set waterwidth and waterheight to the water resolution that will be
8023         // used (often less than the screen resolution for faster rendering)
8024         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8025         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8026
8027         // calculate desired texture sizes
8028         // can't use water if the card does not support the texture size
8029         if (!r_water.integer || r_showsurfaces.integer)
8030                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8031         else if (vid.support.arb_texture_non_power_of_two)
8032         {
8033                 texturewidth = waterwidth;
8034                 textureheight = waterheight;
8035                 camerawidth = waterwidth;
8036                 cameraheight = waterheight;
8037         }
8038         else
8039         {
8040                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8041                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8042                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8043                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8044         }
8045
8046         // allocate textures as needed
8047         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8048         {
8049                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8050                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8051                 {
8052                         if (p->texture_refraction)
8053                                 R_FreeTexture(p->texture_refraction);
8054                         p->texture_refraction = NULL;
8055                         if (p->texture_reflection)
8056                                 R_FreeTexture(p->texture_reflection);
8057                         p->texture_reflection = NULL;
8058                         if (p->texture_camera)
8059                                 R_FreeTexture(p->texture_camera);
8060                         p->texture_camera = NULL;
8061                 }
8062                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8063                 r_waterstate.texturewidth = texturewidth;
8064                 r_waterstate.textureheight = textureheight;
8065                 r_waterstate.camerawidth = camerawidth;
8066                 r_waterstate.cameraheight = cameraheight;
8067         }
8068
8069         if (r_waterstate.texturewidth)
8070         {
8071                 r_waterstate.enabled = true;
8072
8073                 // when doing a reduced render (HDR) we want to use a smaller area
8074                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8075                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8076
8077                 // set up variables that will be used in shader setup
8078                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8079                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8080                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8081                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8082         }
8083
8084         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8085         r_waterstate.numwaterplanes = 0;
8086 }
8087
8088 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8089 {
8090         int triangleindex, planeindex;
8091         const int *e;
8092         vec3_t vert[3];
8093         vec3_t normal;
8094         vec3_t center;
8095         mplane_t plane;
8096         r_waterstate_waterplane_t *p;
8097         texture_t *t = R_GetCurrentTexture(surface->texture);
8098
8099         // just use the first triangle with a valid normal for any decisions
8100         VectorClear(normal);
8101         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8102         {
8103                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8104                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8105                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8106                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8107                 if (VectorLength2(normal) >= 0.001)
8108                         break;
8109         }
8110
8111         VectorCopy(normal, plane.normal);
8112         VectorNormalize(plane.normal);
8113         plane.dist = DotProduct(vert[0], plane.normal);
8114         PlaneClassify(&plane);
8115         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8116         {
8117                 // skip backfaces (except if nocullface is set)
8118                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8119                         return;
8120                 VectorNegate(plane.normal, plane.normal);
8121                 plane.dist *= -1;
8122                 PlaneClassify(&plane);
8123         }
8124
8125
8126         // find a matching plane if there is one
8127         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8128                 if(p->camera_entity == t->camera_entity)
8129                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8130                                 break;
8131         if (planeindex >= r_waterstate.maxwaterplanes)
8132                 return; // nothing we can do, out of planes
8133
8134         // if this triangle does not fit any known plane rendered this frame, add one
8135         if (planeindex >= r_waterstate.numwaterplanes)
8136         {
8137                 // store the new plane
8138                 r_waterstate.numwaterplanes++;
8139                 p->plane = plane;
8140                 // clear materialflags and pvs
8141                 p->materialflags = 0;
8142                 p->pvsvalid = false;
8143                 p->camera_entity = t->camera_entity;
8144                 VectorCopy(surface->mins, p->mins);
8145                 VectorCopy(surface->maxs, p->maxs);
8146         }
8147         else
8148         {
8149                 // merge mins/maxs
8150                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8151                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8152                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8153                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8154                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8155                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8156         }
8157         // merge this surface's materialflags into the waterplane
8158         p->materialflags |= t->currentmaterialflags;
8159         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8160         {
8161                 // merge this surface's PVS into the waterplane
8162                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8163                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8164                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8165                 {
8166                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8167                         p->pvsvalid = true;
8168                 }
8169         }
8170 }
8171
8172 static void R_Water_ProcessPlanes(void)
8173 {
8174         int myscissor[4];
8175         r_refdef_view_t originalview;
8176         r_refdef_view_t myview;
8177         int planeindex;
8178         r_waterstate_waterplane_t *p;
8179         vec3_t visorigin;
8180
8181         originalview = r_refdef.view;
8182
8183         // make sure enough textures are allocated
8184         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8185         {
8186                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8187                 {
8188                         if (!p->texture_refraction)
8189                                 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);
8190                         if (!p->texture_refraction)
8191                                 goto error;
8192                 }
8193                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8194                 {
8195                         if (!p->texture_camera)
8196                                 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);
8197                         if (!p->texture_camera)
8198                                 goto error;
8199                 }
8200
8201                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8202                 {
8203                         if (!p->texture_reflection)
8204                                 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);
8205                         if (!p->texture_reflection)
8206                                 goto error;
8207                 }
8208         }
8209
8210         // render views
8211         r_refdef.view = originalview;
8212         r_refdef.view.showdebug = false;
8213         r_refdef.view.width = r_waterstate.waterwidth;
8214         r_refdef.view.height = r_waterstate.waterheight;
8215         r_refdef.view.useclipplane = true;
8216         myview = r_refdef.view;
8217         r_waterstate.renderingscene = true;
8218         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8219         {
8220                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8221                 {
8222                         r_refdef.view = myview;
8223                         if(r_water_scissormode.integer)
8224                         {
8225                                 R_SetupView(true);
8226                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8227                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8228                         }
8229
8230                         // render reflected scene and copy into texture
8231                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8232                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8233                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8234                         r_refdef.view.clipplane = p->plane;
8235
8236                         // reverse the cullface settings for this render
8237                         r_refdef.view.cullface_front = GL_FRONT;
8238                         r_refdef.view.cullface_back = GL_BACK;
8239                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8240                         {
8241                                 r_refdef.view.usecustompvs = true;
8242                                 if (p->pvsvalid)
8243                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8244                                 else
8245                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8246                         }
8247
8248                         R_ResetViewRendering3D();
8249                         R_ClearScreen(r_refdef.fogenabled);
8250                         if(r_water_scissormode.integer & 2)
8251                                 R_View_UpdateWithScissor(myscissor);
8252                         else
8253                                 R_View_Update();
8254                         if(r_water_scissormode.integer & 1)
8255                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8256                         R_RenderScene();
8257
8258                         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);
8259                 }
8260
8261                 // render the normal view scene and copy into texture
8262                 // (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)
8263                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8264                 {
8265                         r_refdef.view = myview;
8266                         if(r_water_scissormode.integer)
8267                         {
8268                                 R_SetupView(true);
8269                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8270                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8271                         }
8272
8273                         r_waterstate.renderingrefraction = true;
8274
8275                         r_refdef.view.clipplane = p->plane;
8276                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8277                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8278
8279                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8280                         {
8281                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8282                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8283                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8284                                 R_RenderView_UpdateViewVectors();
8285                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8286                                 {
8287                                         r_refdef.view.usecustompvs = true;
8288                                         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);
8289                                 }
8290                         }
8291
8292                         PlaneClassify(&r_refdef.view.clipplane);
8293
8294                         R_ResetViewRendering3D();
8295                         R_ClearScreen(r_refdef.fogenabled);
8296                         if(r_water_scissormode.integer & 2)
8297                                 R_View_UpdateWithScissor(myscissor);
8298                         else
8299                                 R_View_Update();
8300                         if(r_water_scissormode.integer & 1)
8301                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8302                         R_RenderScene();
8303
8304                         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);
8305                         r_waterstate.renderingrefraction = false;
8306                 }
8307                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8308                 {
8309                         r_refdef.view = myview;
8310
8311                         r_refdef.view.clipplane = p->plane;
8312                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8313                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8314
8315                         r_refdef.view.width = r_waterstate.camerawidth;
8316                         r_refdef.view.height = r_waterstate.cameraheight;
8317                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8318                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8319
8320                         if(p->camera_entity)
8321                         {
8322                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8323                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8324                         }
8325
8326                         // note: all of the view is used for displaying... so
8327                         // there is no use in scissoring
8328
8329                         // reverse the cullface settings for this render
8330                         r_refdef.view.cullface_front = GL_FRONT;
8331                         r_refdef.view.cullface_back = GL_BACK;
8332                         // also reverse the view matrix
8333                         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
8334                         R_RenderView_UpdateViewVectors();
8335                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8336                         {
8337                                 r_refdef.view.usecustompvs = true;
8338                                 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);
8339                         }
8340                         
8341                         // camera needs no clipplane
8342                         r_refdef.view.useclipplane = false;
8343
8344                         PlaneClassify(&r_refdef.view.clipplane);
8345
8346                         R_ResetViewRendering3D();
8347                         R_ClearScreen(r_refdef.fogenabled);
8348                         R_View_Update();
8349                         R_RenderScene();
8350
8351                         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);
8352                         r_waterstate.renderingrefraction = false;
8353                 }
8354
8355         }
8356         r_waterstate.renderingscene = false;
8357         r_refdef.view = originalview;
8358         R_ResetViewRendering3D();
8359         R_ClearScreen(r_refdef.fogenabled);
8360         R_View_Update();
8361         return;
8362 error:
8363         r_refdef.view = originalview;
8364         r_waterstate.renderingscene = false;
8365         Cvar_SetValueQuick(&r_water, 0);
8366         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8367         return;
8368 }
8369
8370 void R_Bloom_StartFrame(void)
8371 {
8372         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8373
8374         switch(vid.renderpath)
8375         {
8376         case RENDERPATH_GL20:
8377         case RENDERPATH_D3D9:
8378         case RENDERPATH_D3D10:
8379         case RENDERPATH_D3D11:
8380         case RENDERPATH_SOFT:
8381         case RENDERPATH_GLES2:
8382                 break;
8383         case RENDERPATH_GL13:
8384         case RENDERPATH_GL11:
8385                 return;
8386         }
8387
8388         // set bloomwidth and bloomheight to the bloom resolution that will be
8389         // used (often less than the screen resolution for faster rendering)
8390         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8391         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8392         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8393         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8394         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8395
8396         // calculate desired texture sizes
8397         if (vid.support.arb_texture_non_power_of_two)
8398         {
8399                 screentexturewidth = r_refdef.view.width;
8400                 screentextureheight = r_refdef.view.height;
8401                 bloomtexturewidth = r_bloomstate.bloomwidth;
8402                 bloomtextureheight = r_bloomstate.bloomheight;
8403         }
8404         else
8405         {
8406                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8407                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8408                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8409                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8410         }
8411
8412         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))
8413         {
8414                 Cvar_SetValueQuick(&r_hdr, 0);
8415                 Cvar_SetValueQuick(&r_bloom, 0);
8416                 Cvar_SetValueQuick(&r_motionblur, 0);
8417                 Cvar_SetValueQuick(&r_damageblur, 0);
8418         }
8419
8420         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)))
8421                 screentexturewidth = screentextureheight = 0;
8422         if (!r_hdr.integer && !r_bloom.integer)
8423                 bloomtexturewidth = bloomtextureheight = 0;
8424
8425         // allocate textures as needed
8426         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8427         {
8428                 if (r_bloomstate.texture_screen)
8429                         R_FreeTexture(r_bloomstate.texture_screen);
8430                 r_bloomstate.texture_screen = NULL;
8431                 r_bloomstate.screentexturewidth = screentexturewidth;
8432                 r_bloomstate.screentextureheight = screentextureheight;
8433                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8434                         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);
8435         }
8436         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8437         {
8438                 if (r_bloomstate.texture_bloom)
8439                         R_FreeTexture(r_bloomstate.texture_bloom);
8440                 r_bloomstate.texture_bloom = NULL;
8441                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8442                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8443                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8444                         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);
8445         }
8446
8447         // when doing a reduced render (HDR) we want to use a smaller area
8448         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8449         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8450         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8451         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8452         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8453
8454         // set up a texcoord array for the full resolution screen image
8455         // (we have to keep this around to copy back during final render)
8456         r_bloomstate.screentexcoord2f[0] = 0;
8457         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8458         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8459         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8460         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8461         r_bloomstate.screentexcoord2f[5] = 0;
8462         r_bloomstate.screentexcoord2f[6] = 0;
8463         r_bloomstate.screentexcoord2f[7] = 0;
8464
8465         // set up a texcoord array for the reduced resolution bloom image
8466         // (which will be additive blended over the screen image)
8467         r_bloomstate.bloomtexcoord2f[0] = 0;
8468         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8469         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8470         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8471         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8472         r_bloomstate.bloomtexcoord2f[5] = 0;
8473         r_bloomstate.bloomtexcoord2f[6] = 0;
8474         r_bloomstate.bloomtexcoord2f[7] = 0;
8475
8476         switch(vid.renderpath)
8477         {
8478         case RENDERPATH_GL11:
8479         case RENDERPATH_GL13:
8480         case RENDERPATH_GL20:
8481         case RENDERPATH_SOFT:
8482         case RENDERPATH_GLES2:
8483                 break;
8484         case RENDERPATH_D3D9:
8485         case RENDERPATH_D3D10:
8486         case RENDERPATH_D3D11:
8487                 {
8488                         int i;
8489                         for (i = 0;i < 4;i++)
8490                         {
8491                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8492                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8493                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8494                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8495                         }
8496                 }
8497                 break;
8498         }
8499
8500         if (r_hdr.integer || r_bloom.integer)
8501         {
8502                 r_bloomstate.enabled = true;
8503                 r_bloomstate.hdr = r_hdr.integer != 0;
8504         }
8505
8506         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);
8507 }
8508
8509 void R_Bloom_CopyBloomTexture(float colorscale)
8510 {
8511         r_refdef.stats.bloom++;
8512
8513         // scale down screen texture to the bloom texture size
8514         CHECKGLERROR
8515         R_SetViewport(&r_bloomstate.viewport);
8516         GL_BlendFunc(GL_ONE, GL_ZERO);
8517         GL_Color(colorscale, colorscale, colorscale, 1);
8518         // 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...
8519         switch(vid.renderpath)
8520         {
8521         case RENDERPATH_GL11:
8522         case RENDERPATH_GL13:
8523         case RENDERPATH_GL20:
8524         case RENDERPATH_SOFT:
8525         case RENDERPATH_GLES2:
8526                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8527                 break;
8528         case RENDERPATH_D3D9:
8529         case RENDERPATH_D3D10:
8530         case RENDERPATH_D3D11:
8531                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8532                 break;
8533         }
8534         // TODO: do boxfilter scale-down in shader?
8535         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8536         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8537         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8538
8539         // we now have a bloom image in the framebuffer
8540         // copy it into the bloom image texture for later processing
8541         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);
8542         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8543 }
8544
8545 void R_Bloom_CopyHDRTexture(void)
8546 {
8547         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);
8548         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8549 }
8550
8551 void R_Bloom_MakeTexture(void)
8552 {
8553         int x, range, dir;
8554         float xoffset, yoffset, r, brighten;
8555
8556         r_refdef.stats.bloom++;
8557
8558         R_ResetViewRendering2D();
8559
8560         // we have a bloom image in the framebuffer
8561         CHECKGLERROR
8562         R_SetViewport(&r_bloomstate.viewport);
8563
8564         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8565         {
8566                 x *= 2;
8567                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8568                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8569                 GL_Color(r,r,r,1);
8570                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8571                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8572                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8573                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8574
8575                 // copy the vertically blurred bloom view to a texture
8576                 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);
8577                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8578         }
8579
8580         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8581         brighten = r_bloom_brighten.value;
8582         if (r_hdr.integer)
8583                 brighten *= r_hdr_range.value;
8584         brighten = sqrt(brighten);
8585         if(range >= 1)
8586                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8587         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8588
8589         for (dir = 0;dir < 2;dir++)
8590         {
8591                 // blend on at multiple vertical offsets to achieve a vertical blur
8592                 // TODO: do offset blends using GLSL
8593                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8594                 GL_BlendFunc(GL_ONE, GL_ZERO);
8595                 for (x = -range;x <= range;x++)
8596                 {
8597                         if (!dir){xoffset = 0;yoffset = x;}
8598                         else {xoffset = x;yoffset = 0;}
8599                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8600                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8601                         // compute a texcoord array with the specified x and y offset
8602                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8603                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8604                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8605                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8606                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8607                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8608                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8609                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8610                         // this r value looks like a 'dot' particle, fading sharply to
8611                         // black at the edges
8612                         // (probably not realistic but looks good enough)
8613                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8614                         //r = brighten/(range*2+1);
8615                         r = brighten / (range * 2 + 1);
8616                         if(range >= 1)
8617                                 r *= (1 - x*x/(float)(range*range));
8618                         GL_Color(r, r, r, 1);
8619                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8620                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8621                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8622                         GL_BlendFunc(GL_ONE, GL_ONE);
8623                 }
8624
8625                 // copy the vertically blurred bloom view to a texture
8626                 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);
8627                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8628         }
8629 }
8630
8631 void R_HDR_RenderBloomTexture(void)
8632 {
8633         int oldwidth, oldheight;
8634         float oldcolorscale;
8635         qboolean oldwaterstate;
8636
8637         oldwaterstate = r_waterstate.enabled;
8638         oldcolorscale = r_refdef.view.colorscale;
8639         oldwidth = r_refdef.view.width;
8640         oldheight = r_refdef.view.height;
8641         r_refdef.view.width = r_bloomstate.bloomwidth;
8642         r_refdef.view.height = r_bloomstate.bloomheight;
8643
8644         if(r_hdr.integer < 2)
8645                 r_waterstate.enabled = false;
8646
8647         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8648         // TODO: add exposure compensation features
8649         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8650
8651         r_refdef.view.showdebug = false;
8652         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8653
8654         R_ResetViewRendering3D();
8655
8656         R_ClearScreen(r_refdef.fogenabled);
8657         if (r_timereport_active)
8658                 R_TimeReport("HDRclear");
8659
8660         R_View_Update();
8661         if (r_timereport_active)
8662                 R_TimeReport("visibility");
8663
8664         // only do secondary renders with HDR if r_hdr is 2 or higher
8665         r_waterstate.numwaterplanes = 0;
8666         if (r_waterstate.enabled)
8667                 R_RenderWaterPlanes();
8668
8669         r_refdef.view.showdebug = true;
8670         R_RenderScene();
8671         r_waterstate.numwaterplanes = 0;
8672
8673         R_ResetViewRendering2D();
8674
8675         R_Bloom_CopyHDRTexture();
8676         R_Bloom_MakeTexture();
8677
8678         // restore the view settings
8679         r_waterstate.enabled = oldwaterstate;
8680         r_refdef.view.width = oldwidth;
8681         r_refdef.view.height = oldheight;
8682         r_refdef.view.colorscale = oldcolorscale;
8683
8684         R_ResetViewRendering3D();
8685
8686         R_ClearScreen(r_refdef.fogenabled);
8687         if (r_timereport_active)
8688                 R_TimeReport("viewclear");
8689 }
8690
8691 static void R_BlendView(void)
8692 {
8693         unsigned int permutation;
8694         float uservecs[4][4];
8695
8696         switch (vid.renderpath)
8697         {
8698         case RENDERPATH_GL20:
8699         case RENDERPATH_D3D9:
8700         case RENDERPATH_D3D10:
8701         case RENDERPATH_D3D11:
8702         case RENDERPATH_SOFT:
8703         case RENDERPATH_GLES2:
8704                 permutation =
8705                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8706                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8707                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8708                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8709                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8710
8711                 if (r_bloomstate.texture_screen)
8712                 {
8713                         // make sure the buffer is available
8714                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8715
8716                         R_ResetViewRendering2D();
8717
8718                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8719                         {
8720                                 // declare variables
8721                                 float speed;
8722                                 static float avgspeed;
8723
8724                                 speed = VectorLength(cl.movement_velocity);
8725
8726                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8727                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8728
8729                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8730                                 speed = bound(0, speed, 1);
8731                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8732
8733                                 // calculate values into a standard alpha
8734                                 cl.motionbluralpha = 1 - exp(-
8735                                                 (
8736                                                  (r_motionblur.value * speed / 80)
8737                                                  +
8738                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8739                                                 )
8740                                                 /
8741                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8742                                            );
8743
8744                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8745                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8746                                 // apply the blur
8747                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8748                                 {
8749                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8750                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8751                                         switch(vid.renderpath)
8752                                         {
8753                                         case RENDERPATH_GL11:
8754                                         case RENDERPATH_GL13:
8755                                         case RENDERPATH_GL20:
8756                                         case RENDERPATH_SOFT:
8757                                         case RENDERPATH_GLES2:
8758                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8759                                                 break;
8760                                         case RENDERPATH_D3D9:
8761                                         case RENDERPATH_D3D10:
8762                                         case RENDERPATH_D3D11:
8763                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8764                                                 break;
8765                                         }
8766                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8767                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8768                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8769                                 }
8770                         }
8771
8772                         // copy view into the screen texture
8773                         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);
8774                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8775                 }
8776                 else if (!r_bloomstate.texture_bloom)
8777                 {
8778                         // we may still have to do view tint...
8779                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8780                         {
8781                                 // apply a color tint to the whole view
8782                                 R_ResetViewRendering2D();
8783                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8784                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8785                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8786                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8787                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8788                         }
8789                         break; // no screen processing, no bloom, skip it
8790                 }
8791
8792                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8793                 {
8794                         // render simple bloom effect
8795                         // copy the screen and shrink it and darken it for the bloom process
8796                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8797                         // make the bloom texture
8798                         R_Bloom_MakeTexture();
8799                 }
8800
8801 #if _MSC_VER >= 1400
8802 #define sscanf sscanf_s
8803 #endif
8804                 memset(uservecs, 0, sizeof(uservecs));
8805                 if (r_glsl_postprocess_uservec1_enable.integer)
8806                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8807                 if (r_glsl_postprocess_uservec2_enable.integer)
8808                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8809                 if (r_glsl_postprocess_uservec3_enable.integer)
8810                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8811                 if (r_glsl_postprocess_uservec4_enable.integer)
8812                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8813
8814                 R_ResetViewRendering2D();
8815                 GL_Color(1, 1, 1, 1);
8816                 GL_BlendFunc(GL_ONE, GL_ZERO);
8817
8818                 switch(vid.renderpath)
8819                 {
8820                 case RENDERPATH_GL20:
8821                 case RENDERPATH_GLES2:
8822                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8823                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8824                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
8825                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
8826                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
8827                         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]);
8828                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8829                         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]);
8830                         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]);
8831                         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]);
8832                         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]);
8833                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8834                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8835                         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);
8836                         break;
8837                 case RENDERPATH_D3D9:
8838 #ifdef SUPPORTD3D
8839                         // 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...
8840                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8841                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
8842                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8843                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8844                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8845                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8846                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8847                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8848                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8849                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8850                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8851                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
8852                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
8853                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8854 #endif
8855                         break;
8856                 case RENDERPATH_D3D10:
8857                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8858                         break;
8859                 case RENDERPATH_D3D11:
8860                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8861                         break;
8862                 case RENDERPATH_SOFT:
8863                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8864                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
8865                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8866                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8867                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8868                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8869                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8870                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8871                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8872                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8873                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8874                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
8875                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8876                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8877                         break;
8878                 default:
8879                         break;
8880                 }
8881                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8882                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8883                 break;
8884         case RENDERPATH_GL13:
8885         case RENDERPATH_GL11:
8886                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8887                 {
8888                         // apply a color tint to the whole view
8889                         R_ResetViewRendering2D();
8890                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8891                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8892                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8893                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8894                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8895                 }
8896                 break;
8897         }
8898 }
8899
8900 matrix4x4_t r_waterscrollmatrix;
8901
8902 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8903 {
8904         if (r_refdef.fog_density)
8905         {
8906                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8907                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8908                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8909
8910                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8911                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8912                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8913                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8914
8915                 {
8916                         vec3_t fogvec;
8917                         VectorCopy(r_refdef.fogcolor, fogvec);
8918                         //   color.rgb *= ContrastBoost * SceneBrightness;
8919                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8920                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8921                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8922                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8923                 }
8924         }
8925 }
8926
8927 void R_UpdateVariables(void)
8928 {
8929         R_Textures_Frame();
8930
8931         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8932
8933         r_refdef.farclip = r_farclip_base.value;
8934         if (r_refdef.scene.worldmodel)
8935                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8936         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8937
8938         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8939                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8940         r_refdef.polygonfactor = 0;
8941         r_refdef.polygonoffset = 0;
8942         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8943         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8944
8945         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8946         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8947         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
8948         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8949         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8950         if (FAKELIGHT_ENABLED)
8951         {
8952                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
8953         }
8954         if (r_showsurfaces.integer)
8955         {
8956                 r_refdef.scene.rtworld = false;
8957                 r_refdef.scene.rtworldshadows = false;
8958                 r_refdef.scene.rtdlight = false;
8959                 r_refdef.scene.rtdlightshadows = false;
8960                 r_refdef.lightmapintensity = 0;
8961         }
8962
8963         if (gamemode == GAME_NEHAHRA)
8964         {
8965                 if (gl_fogenable.integer)
8966                 {
8967                         r_refdef.oldgl_fogenable = true;
8968                         r_refdef.fog_density = gl_fogdensity.value;
8969                         r_refdef.fog_red = gl_fogred.value;
8970                         r_refdef.fog_green = gl_foggreen.value;
8971                         r_refdef.fog_blue = gl_fogblue.value;
8972                         r_refdef.fog_alpha = 1;
8973                         r_refdef.fog_start = 0;
8974                         r_refdef.fog_end = gl_skyclip.value;
8975                         r_refdef.fog_height = 1<<30;
8976                         r_refdef.fog_fadedepth = 128;
8977                 }
8978                 else if (r_refdef.oldgl_fogenable)
8979                 {
8980                         r_refdef.oldgl_fogenable = false;
8981                         r_refdef.fog_density = 0;
8982                         r_refdef.fog_red = 0;
8983                         r_refdef.fog_green = 0;
8984                         r_refdef.fog_blue = 0;
8985                         r_refdef.fog_alpha = 0;
8986                         r_refdef.fog_start = 0;
8987                         r_refdef.fog_end = 0;
8988                         r_refdef.fog_height = 1<<30;
8989                         r_refdef.fog_fadedepth = 128;
8990                 }
8991         }
8992
8993         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8994         r_refdef.fog_start = max(0, r_refdef.fog_start);
8995         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8996
8997         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8998
8999         if (r_refdef.fog_density && r_drawfog.integer)
9000         {
9001                 r_refdef.fogenabled = true;
9002                 // this is the point where the fog reaches 0.9986 alpha, which we
9003                 // consider a good enough cutoff point for the texture
9004                 // (0.9986 * 256 == 255.6)
9005                 if (r_fog_exp2.integer)
9006                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9007                 else
9008                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9009                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9010                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9011                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9012                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9013                         R_BuildFogHeightTexture();
9014                 // fog color was already set
9015                 // update the fog texture
9016                 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)
9017                         R_BuildFogTexture();
9018                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9019                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9020         }
9021         else
9022                 r_refdef.fogenabled = false;
9023
9024         switch(vid.renderpath)
9025         {
9026         case RENDERPATH_GL20:
9027         case RENDERPATH_D3D9:
9028         case RENDERPATH_D3D10:
9029         case RENDERPATH_D3D11:
9030         case RENDERPATH_SOFT:
9031         case RENDERPATH_GLES2:
9032                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9033                 {
9034                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9035                         {
9036                                 // build GLSL gamma texture
9037 #define RAMPWIDTH 256
9038                                 unsigned short ramp[RAMPWIDTH * 3];
9039                                 unsigned char rampbgr[RAMPWIDTH][4];
9040                                 int i;
9041
9042                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9043
9044                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9045                                 for(i = 0; i < RAMPWIDTH; ++i)
9046                                 {
9047                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9048                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9049                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9050                                         rampbgr[i][3] = 0;
9051                                 }
9052                                 if (r_texture_gammaramps)
9053                                 {
9054                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9055                                 }
9056                                 else
9057                                 {
9058                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9059                                 }
9060                         }
9061                 }
9062                 else
9063                 {
9064                         // remove GLSL gamma texture
9065                 }
9066                 break;
9067         case RENDERPATH_GL13:
9068         case RENDERPATH_GL11:
9069                 break;
9070         }
9071 }
9072
9073 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9074 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9075 /*
9076 ================
9077 R_SelectScene
9078 ================
9079 */
9080 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9081         if( scenetype != r_currentscenetype ) {
9082                 // store the old scenetype
9083                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9084                 r_currentscenetype = scenetype;
9085                 // move in the new scene
9086                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9087         }
9088 }
9089
9090 /*
9091 ================
9092 R_GetScenePointer
9093 ================
9094 */
9095 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9096 {
9097         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9098         if( scenetype == r_currentscenetype ) {
9099                 return &r_refdef.scene;
9100         } else {
9101                 return &r_scenes_store[ scenetype ];
9102         }
9103 }
9104
9105 /*
9106 ================
9107 R_RenderView
9108 ================
9109 */
9110 int dpsoftrast_test;
9111 void R_RenderView(void)
9112 {
9113         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9114
9115         dpsoftrast_test = r_test.integer;
9116
9117         if (r_timereport_active)
9118                 R_TimeReport("start");
9119         r_textureframe++; // used only by R_GetCurrentTexture
9120         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9121
9122         if(R_CompileShader_CheckStaticParms())
9123                 R_GLSL_Restart_f();
9124
9125         if (!r_drawentities.integer)
9126                 r_refdef.scene.numentities = 0;
9127
9128         R_AnimCache_ClearCache();
9129         R_FrameData_NewFrame();
9130
9131         /* adjust for stereo display */
9132         if(R_Stereo_Active())
9133         {
9134                 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);
9135                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9136         }
9137
9138         if (r_refdef.view.isoverlay)
9139         {
9140                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9141                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9142                 R_TimeReport("depthclear");
9143
9144                 r_refdef.view.showdebug = false;
9145
9146                 r_waterstate.enabled = false;
9147                 r_waterstate.numwaterplanes = 0;
9148
9149                 R_RenderScene();
9150
9151                 r_refdef.view.matrix = originalmatrix;
9152
9153                 CHECKGLERROR
9154                 return;
9155         }
9156
9157         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9158         {
9159                 r_refdef.view.matrix = originalmatrix;
9160                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9161         }
9162
9163         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
9164
9165         R_RenderView_UpdateViewVectors();
9166
9167         R_Shadow_UpdateWorldLightSelection();
9168
9169         R_Bloom_StartFrame();
9170         R_Water_StartFrame();
9171
9172         CHECKGLERROR
9173         if (r_timereport_active)
9174                 R_TimeReport("viewsetup");
9175
9176         R_ResetViewRendering3D();
9177
9178         if (r_refdef.view.clear || r_refdef.fogenabled)
9179         {
9180                 R_ClearScreen(r_refdef.fogenabled);
9181                 if (r_timereport_active)
9182                         R_TimeReport("viewclear");
9183         }
9184         r_refdef.view.clear = true;
9185
9186         // this produces a bloom texture to be used in R_BlendView() later
9187         if (r_hdr.integer && r_bloomstate.bloomwidth)
9188         {
9189                 R_HDR_RenderBloomTexture();
9190                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9191                 r_textureframe++; // used only by R_GetCurrentTexture
9192         }
9193
9194         r_refdef.view.showdebug = true;
9195
9196         R_View_Update();
9197         if (r_timereport_active)
9198                 R_TimeReport("visibility");
9199
9200         r_waterstate.numwaterplanes = 0;
9201         if (r_waterstate.enabled)
9202                 R_RenderWaterPlanes();
9203
9204         R_RenderScene();
9205         r_waterstate.numwaterplanes = 0;
9206
9207         R_BlendView();
9208         if (r_timereport_active)
9209                 R_TimeReport("blendview");
9210
9211         GL_Scissor(0, 0, vid.width, vid.height);
9212         GL_ScissorTest(false);
9213
9214         r_refdef.view.matrix = originalmatrix;
9215
9216         CHECKGLERROR
9217 }
9218
9219 void R_RenderWaterPlanes(void)
9220 {
9221         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9222         {
9223                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9224                 if (r_timereport_active)
9225                         R_TimeReport("waterworld");
9226         }
9227
9228         // don't let sound skip if going slow
9229         if (r_refdef.scene.extraupdate)
9230                 S_ExtraUpdate ();
9231
9232         R_DrawModelsAddWaterPlanes();
9233         if (r_timereport_active)
9234                 R_TimeReport("watermodels");
9235
9236         if (r_waterstate.numwaterplanes)
9237         {
9238                 R_Water_ProcessPlanes();
9239                 if (r_timereport_active)
9240                         R_TimeReport("waterscenes");
9241         }
9242 }
9243
9244 extern void R_DrawLightningBeams (void);
9245 extern void VM_CL_AddPolygonsToMeshQueue (void);
9246 extern void R_DrawPortals (void);
9247 extern cvar_t cl_locs_show;
9248 static void R_DrawLocs(void);
9249 static void R_DrawEntityBBoxes(void);
9250 static void R_DrawModelDecals(void);
9251 extern void R_DrawModelShadows(void);
9252 extern void R_DrawModelShadowMaps(void);
9253 extern cvar_t cl_decals_newsystem;
9254 extern qboolean r_shadow_usingdeferredprepass;
9255 void R_RenderScene(void)
9256 {
9257         qboolean shadowmapping = false;
9258
9259         if (r_timereport_active)
9260                 R_TimeReport("beginscene");
9261
9262         r_refdef.stats.renders++;
9263
9264         R_UpdateFogColor();
9265
9266         // don't let sound skip if going slow
9267         if (r_refdef.scene.extraupdate)
9268                 S_ExtraUpdate ();
9269
9270         R_MeshQueue_BeginScene();
9271
9272         R_SkyStartFrame();
9273
9274         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);
9275
9276         if (r_timereport_active)
9277                 R_TimeReport("skystartframe");
9278
9279         if (cl.csqc_vidvars.drawworld)
9280         {
9281                 // don't let sound skip if going slow
9282                 if (r_refdef.scene.extraupdate)
9283                         S_ExtraUpdate ();
9284
9285                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9286                 {
9287                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9288                         if (r_timereport_active)
9289                                 R_TimeReport("worldsky");
9290                 }
9291
9292                 if (R_DrawBrushModelsSky() && r_timereport_active)
9293                         R_TimeReport("bmodelsky");
9294
9295                 if (skyrendermasked && skyrenderlater)
9296                 {
9297                         // we have to force off the water clipping plane while rendering sky
9298                         R_SetupView(false);
9299                         R_Sky();
9300                         R_SetupView(true);
9301                         if (r_timereport_active)
9302                                 R_TimeReport("sky");
9303                 }
9304         }
9305
9306         R_AnimCache_CacheVisibleEntities();
9307         if (r_timereport_active)
9308                 R_TimeReport("animation");
9309
9310         R_Shadow_PrepareLights();
9311         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9312                 R_Shadow_PrepareModelShadows();
9313         if (r_timereport_active)
9314                 R_TimeReport("preparelights");
9315
9316         if (R_Shadow_ShadowMappingEnabled())
9317                 shadowmapping = true;
9318
9319         if (r_shadow_usingdeferredprepass)
9320                 R_Shadow_DrawPrepass();
9321
9322         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9323         {
9324                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9325                 if (r_timereport_active)
9326                         R_TimeReport("worlddepth");
9327         }
9328         if (r_depthfirst.integer >= 2)
9329         {
9330                 R_DrawModelsDepth();
9331                 if (r_timereport_active)
9332                         R_TimeReport("modeldepth");
9333         }
9334
9335         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9336         {
9337                 R_DrawModelShadowMaps();
9338                 R_ResetViewRendering3D();
9339                 // don't let sound skip if going slow
9340                 if (r_refdef.scene.extraupdate)
9341                         S_ExtraUpdate ();
9342         }
9343
9344         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9345         {
9346                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9347                 if (r_timereport_active)
9348                         R_TimeReport("world");
9349         }
9350
9351         // don't let sound skip if going slow
9352         if (r_refdef.scene.extraupdate)
9353                 S_ExtraUpdate ();
9354
9355         R_DrawModels();
9356         if (r_timereport_active)
9357                 R_TimeReport("models");
9358
9359         // don't let sound skip if going slow
9360         if (r_refdef.scene.extraupdate)
9361                 S_ExtraUpdate ();
9362
9363         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9364         {
9365                 R_DrawModelShadows();
9366                 R_ResetViewRendering3D();
9367                 // don't let sound skip if going slow
9368                 if (r_refdef.scene.extraupdate)
9369                         S_ExtraUpdate ();
9370         }
9371
9372         if (!r_shadow_usingdeferredprepass)
9373         {
9374                 R_Shadow_DrawLights();
9375                 if (r_timereport_active)
9376                         R_TimeReport("rtlights");
9377         }
9378
9379         // don't let sound skip if going slow
9380         if (r_refdef.scene.extraupdate)
9381                 S_ExtraUpdate ();
9382
9383         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9384         {
9385                 R_DrawModelShadows();
9386                 R_ResetViewRendering3D();
9387                 // don't let sound skip if going slow
9388                 if (r_refdef.scene.extraupdate)
9389                         S_ExtraUpdate ();
9390         }
9391
9392         if (cl.csqc_vidvars.drawworld)
9393         {
9394                 if (cl_decals_newsystem.integer)
9395                 {
9396                         R_DrawModelDecals();
9397                         if (r_timereport_active)
9398                                 R_TimeReport("modeldecals");
9399                 }
9400                 else
9401                 {
9402                         R_DrawDecals();
9403                         if (r_timereport_active)
9404                                 R_TimeReport("decals");
9405                 }
9406
9407                 R_DrawParticles();
9408                 if (r_timereport_active)
9409                         R_TimeReport("particles");
9410
9411                 R_DrawExplosions();
9412                 if (r_timereport_active)
9413                         R_TimeReport("explosions");
9414
9415                 R_DrawLightningBeams();
9416                 if (r_timereport_active)
9417                         R_TimeReport("lightning");
9418         }
9419
9420         VM_CL_AddPolygonsToMeshQueue();
9421
9422         if (r_refdef.view.showdebug)
9423         {
9424                 if (cl_locs_show.integer)
9425                 {
9426                         R_DrawLocs();
9427                         if (r_timereport_active)
9428                                 R_TimeReport("showlocs");
9429                 }
9430
9431                 if (r_drawportals.integer)
9432                 {
9433                         R_DrawPortals();
9434                         if (r_timereport_active)
9435                                 R_TimeReport("portals");
9436                 }
9437
9438                 if (r_showbboxes.value > 0)
9439                 {
9440                         R_DrawEntityBBoxes();
9441                         if (r_timereport_active)
9442                                 R_TimeReport("bboxes");
9443                 }
9444         }
9445
9446         R_MeshQueue_RenderTransparent();
9447         if (r_timereport_active)
9448                 R_TimeReport("drawtrans");
9449
9450         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))
9451         {
9452                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9453                 if (r_timereport_active)
9454                         R_TimeReport("worlddebug");
9455                 R_DrawModelsDebug();
9456                 if (r_timereport_active)
9457                         R_TimeReport("modeldebug");
9458         }
9459
9460         if (cl.csqc_vidvars.drawworld)
9461         {
9462                 R_Shadow_DrawCoronas();
9463                 if (r_timereport_active)
9464                         R_TimeReport("coronas");
9465         }
9466
9467 #if 0
9468         {
9469                 GL_DepthTest(false);
9470                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9471                 GL_Color(1, 1, 1, 1);
9472                 qglBegin(GL_POLYGON);
9473                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9474                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9475                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9476                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9477                 qglEnd();
9478                 qglBegin(GL_POLYGON);
9479                 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]);
9480                 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]);
9481                 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]);
9482                 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]);
9483                 qglEnd();
9484                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9485         }
9486 #endif
9487
9488         // don't let sound skip if going slow
9489         if (r_refdef.scene.extraupdate)
9490                 S_ExtraUpdate ();
9491
9492         R_ResetViewRendering2D();
9493 }
9494
9495 static const unsigned short bboxelements[36] =
9496 {
9497         5, 1, 3, 5, 3, 7,
9498         6, 2, 0, 6, 0, 4,
9499         7, 3, 2, 7, 2, 6,
9500         4, 0, 1, 4, 1, 5,
9501         4, 5, 7, 4, 7, 6,
9502         1, 0, 2, 1, 2, 3,
9503 };
9504
9505 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9506 {
9507         int i;
9508         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9509
9510         RSurf_ActiveWorldEntity();
9511
9512         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9513         GL_DepthMask(false);
9514         GL_DepthRange(0, 1);
9515         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9516 //      R_Mesh_ResetTextureState();
9517
9518         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9519         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9520         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9521         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9522         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9523         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9524         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9525         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9526         R_FillColors(color4f, 8, cr, cg, cb, ca);
9527         if (r_refdef.fogenabled)
9528         {
9529                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9530                 {
9531                         f1 = RSurf_FogVertex(v);
9532                         f2 = 1 - f1;
9533                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9534                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9535                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9536                 }
9537         }
9538         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9539         R_Mesh_ResetTextureState();
9540         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9541         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9542 }
9543
9544 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9545 {
9546         int i;
9547         float color[4];
9548         prvm_edict_t *edict;
9549         prvm_prog_t *prog_save = prog;
9550
9551         // this function draws bounding boxes of server entities
9552         if (!sv.active)
9553                 return;
9554
9555         GL_CullFace(GL_NONE);
9556         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9557
9558         prog = 0;
9559         SV_VM_Begin();
9560         for (i = 0;i < numsurfaces;i++)
9561         {
9562                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9563                 switch ((int)edict->fields.server->solid)
9564                 {
9565                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9566                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9567                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9568                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9569                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9570                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9571                 }
9572                 color[3] *= r_showbboxes.value;
9573                 color[3] = bound(0, color[3], 1);
9574                 GL_DepthTest(!r_showdisabledepthtest.integer);
9575                 GL_CullFace(r_refdef.view.cullface_front);
9576                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9577         }
9578         SV_VM_End();
9579         prog = prog_save;
9580 }
9581
9582 static void R_DrawEntityBBoxes(void)
9583 {
9584         int i;
9585         prvm_edict_t *edict;
9586         vec3_t center;
9587         prvm_prog_t *prog_save = prog;
9588
9589         // this function draws bounding boxes of server entities
9590         if (!sv.active)
9591                 return;
9592
9593         prog = 0;
9594         SV_VM_Begin();
9595         for (i = 0;i < prog->num_edicts;i++)
9596         {
9597                 edict = PRVM_EDICT_NUM(i);
9598                 if (edict->priv.server->free)
9599                         continue;
9600                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9601                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9602                         continue;
9603                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9604                         continue;
9605                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9606                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9607         }
9608         SV_VM_End();
9609         prog = prog_save;
9610 }
9611
9612 static const int nomodelelement3i[24] =
9613 {
9614         5, 2, 0,
9615         5, 1, 2,
9616         5, 0, 3,
9617         5, 3, 1,
9618         0, 2, 4,
9619         2, 1, 4,
9620         3, 0, 4,
9621         1, 3, 4
9622 };
9623
9624 static const unsigned short nomodelelement3s[24] =
9625 {
9626         5, 2, 0,
9627         5, 1, 2,
9628         5, 0, 3,
9629         5, 3, 1,
9630         0, 2, 4,
9631         2, 1, 4,
9632         3, 0, 4,
9633         1, 3, 4
9634 };
9635
9636 static const float nomodelvertex3f[6*3] =
9637 {
9638         -16,   0,   0,
9639          16,   0,   0,
9640           0, -16,   0,
9641           0,  16,   0,
9642           0,   0, -16,
9643           0,   0,  16
9644 };
9645
9646 static const float nomodelcolor4f[6*4] =
9647 {
9648         0.0f, 0.0f, 0.5f, 1.0f,
9649         0.0f, 0.0f, 0.5f, 1.0f,
9650         0.0f, 0.5f, 0.0f, 1.0f,
9651         0.0f, 0.5f, 0.0f, 1.0f,
9652         0.5f, 0.0f, 0.0f, 1.0f,
9653         0.5f, 0.0f, 0.0f, 1.0f
9654 };
9655
9656 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9657 {
9658         int i;
9659         float f1, f2, *c;
9660         float color4f[6*4];
9661
9662         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);
9663
9664         // this is only called once per entity so numsurfaces is always 1, and
9665         // surfacelist is always {0}, so this code does not handle batches
9666
9667         if (rsurface.ent_flags & RENDER_ADDITIVE)
9668         {
9669                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9670                 GL_DepthMask(false);
9671         }
9672         else if (rsurface.colormod[3] < 1)
9673         {
9674                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9675                 GL_DepthMask(false);
9676         }
9677         else
9678         {
9679                 GL_BlendFunc(GL_ONE, GL_ZERO);
9680                 GL_DepthMask(true);
9681         }
9682         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9683         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9684         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9685         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9686         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9687         for (i = 0, c = color4f;i < 6;i++, c += 4)
9688         {
9689                 c[0] *= rsurface.colormod[0];
9690                 c[1] *= rsurface.colormod[1];
9691                 c[2] *= rsurface.colormod[2];
9692                 c[3] *= rsurface.colormod[3];
9693         }
9694         if (r_refdef.fogenabled)
9695         {
9696                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9697                 {
9698                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9699                         f2 = 1 - f1;
9700                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9701                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9702                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9703                 }
9704         }
9705 //      R_Mesh_ResetTextureState();
9706         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9707         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9708         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9709 }
9710
9711 void R_DrawNoModel(entity_render_t *ent)
9712 {
9713         vec3_t org;
9714         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9715         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9716                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9717         else
9718                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9719 }
9720
9721 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9722 {
9723         vec3_t right1, right2, diff, normal;
9724
9725         VectorSubtract (org2, org1, normal);
9726
9727         // calculate 'right' vector for start
9728         VectorSubtract (r_refdef.view.origin, org1, diff);
9729         CrossProduct (normal, diff, right1);
9730         VectorNormalize (right1);
9731
9732         // calculate 'right' vector for end
9733         VectorSubtract (r_refdef.view.origin, org2, diff);
9734         CrossProduct (normal, diff, right2);
9735         VectorNormalize (right2);
9736
9737         vert[ 0] = org1[0] + width * right1[0];
9738         vert[ 1] = org1[1] + width * right1[1];
9739         vert[ 2] = org1[2] + width * right1[2];
9740         vert[ 3] = org1[0] - width * right1[0];
9741         vert[ 4] = org1[1] - width * right1[1];
9742         vert[ 5] = org1[2] - width * right1[2];
9743         vert[ 6] = org2[0] - width * right2[0];
9744         vert[ 7] = org2[1] - width * right2[1];
9745         vert[ 8] = org2[2] - width * right2[2];
9746         vert[ 9] = org2[0] + width * right2[0];
9747         vert[10] = org2[1] + width * right2[1];
9748         vert[11] = org2[2] + width * right2[2];
9749 }
9750
9751 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)
9752 {
9753         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9754         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9755         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9756         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9757         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9758         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9759         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9760         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9761         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9762         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9763         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9764         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9765 }
9766
9767 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9768 {
9769         int i;
9770         float *vertex3f;
9771         float v[3];
9772         VectorSet(v, x, y, z);
9773         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9774                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9775                         break;
9776         if (i == mesh->numvertices)
9777         {
9778                 if (mesh->numvertices < mesh->maxvertices)
9779                 {
9780                         VectorCopy(v, vertex3f);
9781                         mesh->numvertices++;
9782                 }
9783                 return mesh->numvertices;
9784         }
9785         else
9786                 return i;
9787 }
9788
9789 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9790 {
9791         int i;
9792         int *e, element[3];
9793         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9794         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9795         e = mesh->element3i + mesh->numtriangles * 3;
9796         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9797         {
9798                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9799                 if (mesh->numtriangles < mesh->maxtriangles)
9800                 {
9801                         *e++ = element[0];
9802                         *e++ = element[1];
9803                         *e++ = element[2];
9804                         mesh->numtriangles++;
9805                 }
9806                 element[1] = element[2];
9807         }
9808 }
9809
9810 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9811 {
9812         int i;
9813         int *e, element[3];
9814         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9815         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9816         e = mesh->element3i + mesh->numtriangles * 3;
9817         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9818         {
9819                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[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 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9832 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9833 {
9834         int planenum, planenum2;
9835         int w;
9836         int tempnumpoints;
9837         mplane_t *plane, *plane2;
9838         double maxdist;
9839         double temppoints[2][256*3];
9840         // figure out how large a bounding box we need to properly compute this brush
9841         maxdist = 0;
9842         for (w = 0;w < numplanes;w++)
9843                 maxdist = max(maxdist, fabs(planes[w].dist));
9844         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9845         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9846         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9847         {
9848                 w = 0;
9849                 tempnumpoints = 4;
9850                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9851                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9852                 {
9853                         if (planenum2 == planenum)
9854                                 continue;
9855                         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);
9856                         w = !w;
9857                 }
9858                 if (tempnumpoints < 3)
9859                         continue;
9860                 // generate elements forming a triangle fan for this polygon
9861                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9862         }
9863 }
9864
9865 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)
9866 {
9867         texturelayer_t *layer;
9868         layer = t->currentlayers + t->currentnumlayers++;
9869         layer->type = type;
9870         layer->depthmask = depthmask;
9871         layer->blendfunc1 = blendfunc1;
9872         layer->blendfunc2 = blendfunc2;
9873         layer->texture = texture;
9874         layer->texmatrix = *matrix;
9875         layer->color[0] = r;
9876         layer->color[1] = g;
9877         layer->color[2] = b;
9878         layer->color[3] = a;
9879 }
9880
9881 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9882 {
9883         if(parms[0] == 0 && parms[1] == 0)
9884                 return false;
9885         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9886                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9887                         return false;
9888         return true;
9889 }
9890
9891 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9892 {
9893         double index, f;
9894         index = parms[2] + r_refdef.scene.time * parms[3];
9895         index -= floor(index);
9896         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9897         {
9898         default:
9899         case Q3WAVEFUNC_NONE:
9900         case Q3WAVEFUNC_NOISE:
9901         case Q3WAVEFUNC_COUNT:
9902                 f = 0;
9903                 break;
9904         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9905         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9906         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9907         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9908         case Q3WAVEFUNC_TRIANGLE:
9909                 index *= 4;
9910                 f = index - floor(index);
9911                 if (index < 1)
9912                         f = f;
9913                 else if (index < 2)
9914                         f = 1 - f;
9915                 else if (index < 3)
9916                         f = -f;
9917                 else
9918                         f = -(1 - f);
9919                 break;
9920         }
9921         f = parms[0] + parms[1] * f;
9922         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9923                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
9924         return (float) f;
9925 }
9926
9927 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9928 {
9929         int w, h, idx;
9930         float f;
9931         float tcmat[12];
9932         matrix4x4_t matrix, temp;
9933         switch(tcmod->tcmod)
9934         {
9935                 case Q3TCMOD_COUNT:
9936                 case Q3TCMOD_NONE:
9937                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9938                                 matrix = r_waterscrollmatrix;
9939                         else
9940                                 matrix = identitymatrix;
9941                         break;
9942                 case Q3TCMOD_ENTITYTRANSLATE:
9943                         // this is used in Q3 to allow the gamecode to control texcoord
9944                         // scrolling on the entity, which is not supported in darkplaces yet.
9945                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9946                         break;
9947                 case Q3TCMOD_ROTATE:
9948                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9949                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9950                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9951                         break;
9952                 case Q3TCMOD_SCALE:
9953                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9954                         break;
9955                 case Q3TCMOD_SCROLL:
9956                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9957                         break;
9958                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9959                         w = (int) tcmod->parms[0];
9960                         h = (int) tcmod->parms[1];
9961                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9962                         f = f - floor(f);
9963                         idx = (int) floor(f * w * h);
9964                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9965                         break;
9966                 case Q3TCMOD_STRETCH:
9967                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9968                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9969                         break;
9970                 case Q3TCMOD_TRANSFORM:
9971                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
9972                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
9973                         VectorSet(tcmat +  6, 0                   , 0                , 1);
9974                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
9975                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9976                         break;
9977                 case Q3TCMOD_TURBULENT:
9978                         // this is handled in the RSurf_PrepareVertices function
9979                         matrix = identitymatrix;
9980                         break;
9981         }
9982         temp = *texmatrix;
9983         Matrix4x4_Concat(texmatrix, &matrix, &temp);
9984 }
9985
9986 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9987 {
9988         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9989         char name[MAX_QPATH];
9990         skinframe_t *skinframe;
9991         unsigned char pixels[296*194];
9992         strlcpy(cache->name, skinname, sizeof(cache->name));
9993         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9994         if (developer_loading.integer)
9995                 Con_Printf("loading %s\n", name);
9996         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9997         if (!skinframe || !skinframe->base)
9998         {
9999                 unsigned char *f;
10000                 fs_offset_t filesize;
10001                 skinframe = NULL;
10002                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10003                 if (f)
10004                 {
10005                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10006                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10007                         Mem_Free(f);
10008                 }
10009         }
10010         cache->skinframe = skinframe;
10011 }
10012
10013 texture_t *R_GetCurrentTexture(texture_t *t)
10014 {
10015         int i;
10016         const entity_render_t *ent = rsurface.entity;
10017         dp_model_t *model = ent->model;
10018         q3shaderinfo_layer_tcmod_t *tcmod;
10019
10020         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10021                 return t->currentframe;
10022         t->update_lastrenderframe = r_textureframe;
10023         t->update_lastrenderentity = (void *)ent;
10024
10025         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10026                 t->camera_entity = ent->entitynumber;
10027         else
10028                 t->camera_entity = 0;
10029
10030         // switch to an alternate material if this is a q1bsp animated material
10031         {
10032                 texture_t *texture = t;
10033                 int s = rsurface.ent_skinnum;
10034                 if ((unsigned int)s >= (unsigned int)model->numskins)
10035                         s = 0;
10036                 if (model->skinscenes)
10037                 {
10038                         if (model->skinscenes[s].framecount > 1)
10039                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10040                         else
10041                                 s = model->skinscenes[s].firstframe;
10042                 }
10043                 if (s > 0)
10044                         t = t + s * model->num_surfaces;
10045                 if (t->animated)
10046                 {
10047                         // use an alternate animation if the entity's frame is not 0,
10048                         // and only if the texture has an alternate animation
10049                         if (rsurface.ent_alttextures && t->anim_total[1])
10050                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10051                         else
10052                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10053                 }
10054                 texture->currentframe = t;
10055         }
10056
10057         // update currentskinframe to be a qw skin or animation frame
10058         if (rsurface.ent_qwskin >= 0)
10059         {
10060                 i = rsurface.ent_qwskin;
10061                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10062                 {
10063                         r_qwskincache_size = cl.maxclients;
10064                         if (r_qwskincache)
10065                                 Mem_Free(r_qwskincache);
10066                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10067                 }
10068                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10069                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10070                 t->currentskinframe = r_qwskincache[i].skinframe;
10071                 if (t->currentskinframe == NULL)
10072                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10073         }
10074         else if (t->numskinframes >= 2)
10075                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10076         if (t->backgroundnumskinframes >= 2)
10077                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10078
10079         t->currentmaterialflags = t->basematerialflags;
10080         t->currentalpha = rsurface.colormod[3];
10081         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10082                 t->currentalpha *= r_wateralpha.value;
10083         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10084                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10085         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10086                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10087         if (!(rsurface.ent_flags & RENDER_LIGHT))
10088                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10089         else if (FAKELIGHT_ENABLED)
10090         {
10091                         // no modellight if using fakelight for the map
10092         }
10093         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10094         {
10095                 // pick a model lighting mode
10096                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10097                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10098                 else
10099                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10100         }
10101         if (rsurface.ent_flags & RENDER_ADDITIVE)
10102                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10103         else if (t->currentalpha < 1)
10104                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10105         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10106                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10107         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10108                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10109         if (t->backgroundnumskinframes)
10110                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10111         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10112         {
10113                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10114                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10115         }
10116         else
10117                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10118         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10119                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10120
10121         // there is no tcmod
10122         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10123         {
10124                 t->currenttexmatrix = r_waterscrollmatrix;
10125                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10126         }
10127         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10128         {
10129                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10130                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10131         }
10132
10133         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10134                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10135         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10136                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10137
10138         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10139         if (t->currentskinframe->qpixels)
10140                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10141         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10142         if (!t->basetexture)
10143                 t->basetexture = r_texture_notexture;
10144         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10145         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10146         t->nmaptexture = t->currentskinframe->nmap;
10147         if (!t->nmaptexture)
10148                 t->nmaptexture = r_texture_blanknormalmap;
10149         t->glosstexture = r_texture_black;
10150         t->glowtexture = t->currentskinframe->glow;
10151         t->fogtexture = t->currentskinframe->fog;
10152         t->reflectmasktexture = t->currentskinframe->reflect;
10153         if (t->backgroundnumskinframes)
10154         {
10155                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10156                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10157                 t->backgroundglosstexture = r_texture_black;
10158                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10159                 if (!t->backgroundnmaptexture)
10160                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10161         }
10162         else
10163         {
10164                 t->backgroundbasetexture = r_texture_white;
10165                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10166                 t->backgroundglosstexture = r_texture_black;
10167                 t->backgroundglowtexture = NULL;
10168         }
10169         t->specularpower = r_shadow_glossexponent.value;
10170         // TODO: store reference values for these in the texture?
10171         t->specularscale = 0;
10172         if (r_shadow_gloss.integer > 0)
10173         {
10174                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10175                 {
10176                         if (r_shadow_glossintensity.value > 0)
10177                         {
10178                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10179                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10180                                 t->specularscale = r_shadow_glossintensity.value;
10181                         }
10182                 }
10183                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10184                 {
10185                         t->glosstexture = r_texture_white;
10186                         t->backgroundglosstexture = r_texture_white;
10187                         t->specularscale = r_shadow_gloss2intensity.value;
10188                         t->specularpower = r_shadow_gloss2exponent.value;
10189                 }
10190         }
10191         t->specularscale *= t->specularscalemod;
10192         t->specularpower *= t->specularpowermod;
10193
10194         // lightmaps mode looks bad with dlights using actual texturing, so turn
10195         // off the colormap and glossmap, but leave the normalmap on as it still
10196         // accurately represents the shading involved
10197         if (gl_lightmaps.integer)
10198         {
10199                 t->basetexture = r_texture_grey128;
10200                 t->pantstexture = r_texture_black;
10201                 t->shirttexture = r_texture_black;
10202                 t->nmaptexture = r_texture_blanknormalmap;
10203                 t->glosstexture = r_texture_black;
10204                 t->glowtexture = NULL;
10205                 t->fogtexture = NULL;
10206                 t->reflectmasktexture = NULL;
10207                 t->backgroundbasetexture = NULL;
10208                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10209                 t->backgroundglosstexture = r_texture_black;
10210                 t->backgroundglowtexture = NULL;
10211                 t->specularscale = 0;
10212                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10213         }
10214
10215         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10216         VectorClear(t->dlightcolor);
10217         t->currentnumlayers = 0;
10218         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10219         {
10220                 int blendfunc1, blendfunc2;
10221                 qboolean depthmask;
10222                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10223                 {
10224                         blendfunc1 = GL_SRC_ALPHA;
10225                         blendfunc2 = GL_ONE;
10226                 }
10227                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10228                 {
10229                         blendfunc1 = GL_SRC_ALPHA;
10230                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10231                 }
10232                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10233                 {
10234                         blendfunc1 = t->customblendfunc[0];
10235                         blendfunc2 = t->customblendfunc[1];
10236                 }
10237                 else
10238                 {
10239                         blendfunc1 = GL_ONE;
10240                         blendfunc2 = GL_ZERO;
10241                 }
10242                 // don't colormod evilblend textures
10243                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10244                         VectorSet(t->lightmapcolor, 1, 1, 1);
10245                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10246                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10247                 {
10248                         // fullbright is not affected by r_refdef.lightmapintensity
10249                         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]);
10250                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10251                                 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]);
10252                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10253                                 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]);
10254                 }
10255                 else
10256                 {
10257                         vec3_t ambientcolor;
10258                         float colorscale;
10259                         // set the color tint used for lights affecting this surface
10260                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10261                         colorscale = 2;
10262                         // q3bsp has no lightmap updates, so the lightstylevalue that
10263                         // would normally be baked into the lightmap must be
10264                         // applied to the color
10265                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10266                         if (model->type == mod_brushq3)
10267                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10268                         colorscale *= r_refdef.lightmapintensity;
10269                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10270                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10271                         // basic lit geometry
10272                         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]);
10273                         // add pants/shirt if needed
10274                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10275                                 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]);
10276                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10277                                 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]);
10278                         // now add ambient passes if needed
10279                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10280                         {
10281                                 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]);
10282                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10283                                         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]);
10284                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10285                                         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]);
10286                         }
10287                 }
10288                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10289                         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]);
10290                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10291                 {
10292                         // if this is opaque use alpha blend which will darken the earlier
10293                         // passes cheaply.
10294                         //
10295                         // if this is an alpha blended material, all the earlier passes
10296                         // were darkened by fog already, so we only need to add the fog
10297                         // color ontop through the fog mask texture
10298                         //
10299                         // if this is an additive blended material, all the earlier passes
10300                         // were darkened by fog already, and we should not add fog color
10301                         // (because the background was not darkened, there is no fog color
10302                         // that was lost behind it).
10303                         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]);
10304                 }
10305         }
10306
10307         return t->currentframe;
10308 }
10309
10310 rsurfacestate_t rsurface;
10311
10312 void RSurf_ActiveWorldEntity(void)
10313 {
10314         dp_model_t *model = r_refdef.scene.worldmodel;
10315         //if (rsurface.entity == r_refdef.scene.worldentity)
10316         //      return;
10317         rsurface.entity = r_refdef.scene.worldentity;
10318         rsurface.skeleton = NULL;
10319         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10320         rsurface.ent_skinnum = 0;
10321         rsurface.ent_qwskin = -1;
10322         rsurface.ent_shadertime = 0;
10323         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10324         rsurface.matrix = identitymatrix;
10325         rsurface.inversematrix = identitymatrix;
10326         rsurface.matrixscale = 1;
10327         rsurface.inversematrixscale = 1;
10328         R_EntityMatrix(&identitymatrix);
10329         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10330         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10331         rsurface.fograngerecip = r_refdef.fograngerecip;
10332         rsurface.fogheightfade = r_refdef.fogheightfade;
10333         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10334         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10335         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10336         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10337         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10338         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10339         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10340         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10341         rsurface.colormod[3] = 1;
10342         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);
10343         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10344         rsurface.frameblend[0].lerp = 1;
10345         rsurface.ent_alttextures = false;
10346         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10347         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10348         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10349         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10350         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10351         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10352         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10353         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10354         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10355         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10356         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10357         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10358         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10359         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10360         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10361         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10362         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10363         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10364         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10365         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10366         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10367         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10368         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10369         rsurface.modelelement3i = model->surfmesh.data_element3i;
10370         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10371         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10372         rsurface.modelelement3s = model->surfmesh.data_element3s;
10373         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10374         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10375         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10376         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10377         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10378         rsurface.modelsurfaces = model->data_surfaces;
10379         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10380         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10381         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10382         rsurface.modelgeneratedvertex = false;
10383         rsurface.batchgeneratedvertex = false;
10384         rsurface.batchfirstvertex = 0;
10385         rsurface.batchnumvertices = 0;
10386         rsurface.batchfirsttriangle = 0;
10387         rsurface.batchnumtriangles = 0;
10388         rsurface.batchvertex3f  = NULL;
10389         rsurface.batchvertex3f_vertexbuffer = NULL;
10390         rsurface.batchvertex3f_bufferoffset = 0;
10391         rsurface.batchsvector3f = NULL;
10392         rsurface.batchsvector3f_vertexbuffer = NULL;
10393         rsurface.batchsvector3f_bufferoffset = 0;
10394         rsurface.batchtvector3f = NULL;
10395         rsurface.batchtvector3f_vertexbuffer = NULL;
10396         rsurface.batchtvector3f_bufferoffset = 0;
10397         rsurface.batchnormal3f  = NULL;
10398         rsurface.batchnormal3f_vertexbuffer = NULL;
10399         rsurface.batchnormal3f_bufferoffset = 0;
10400         rsurface.batchlightmapcolor4f = NULL;
10401         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10402         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10403         rsurface.batchtexcoordtexture2f = NULL;
10404         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10405         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10406         rsurface.batchtexcoordlightmap2f = NULL;
10407         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10408         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10409         rsurface.batchvertexmesh = NULL;
10410         rsurface.batchvertexmeshbuffer = NULL;
10411         rsurface.batchvertex3fbuffer = NULL;
10412         rsurface.batchelement3i = NULL;
10413         rsurface.batchelement3i_indexbuffer = NULL;
10414         rsurface.batchelement3i_bufferoffset = 0;
10415         rsurface.batchelement3s = NULL;
10416         rsurface.batchelement3s_indexbuffer = NULL;
10417         rsurface.batchelement3s_bufferoffset = 0;
10418         rsurface.passcolor4f = NULL;
10419         rsurface.passcolor4f_vertexbuffer = NULL;
10420         rsurface.passcolor4f_bufferoffset = 0;
10421 }
10422
10423 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10424 {
10425         dp_model_t *model = ent->model;
10426         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10427         //      return;
10428         rsurface.entity = (entity_render_t *)ent;
10429         rsurface.skeleton = ent->skeleton;
10430         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10431         rsurface.ent_skinnum = ent->skinnum;
10432         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;
10433         rsurface.ent_shadertime = ent->shadertime;
10434         rsurface.ent_flags = ent->flags;
10435         rsurface.matrix = ent->matrix;
10436         rsurface.inversematrix = ent->inversematrix;
10437         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10438         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10439         R_EntityMatrix(&rsurface.matrix);
10440         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10441         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10442         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10443         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10444         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10445         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10446         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10447         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10448         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10449         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10450         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10451         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10452         rsurface.colormod[3] = ent->alpha;
10453         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10454         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10455         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10456         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10457         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10458         if (ent->model->brush.submodel && !prepass)
10459         {
10460                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10461                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10462         }
10463         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10464         {
10465                 if (ent->animcache_vertex3f)
10466                 {
10467                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10468                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10469                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10470                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10471                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10472                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10473                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
10474                 }
10475                 else if (wanttangents)
10476                 {
10477                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10478                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10479                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10480                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10481                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
10482                         rsurface.modelvertexmesh = NULL;
10483                         rsurface.modelvertexmeshbuffer = NULL;
10484                         rsurface.modelvertex3fbuffer = NULL;
10485                 }
10486                 else if (wantnormals)
10487                 {
10488                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10489                         rsurface.modelsvector3f = NULL;
10490                         rsurface.modeltvector3f = NULL;
10491                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10492                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
10493                         rsurface.modelvertexmesh = NULL;
10494                         rsurface.modelvertexmeshbuffer = NULL;
10495                         rsurface.modelvertex3fbuffer = NULL;
10496                 }
10497                 else
10498                 {
10499                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10500                         rsurface.modelsvector3f = NULL;
10501                         rsurface.modeltvector3f = NULL;
10502                         rsurface.modelnormal3f = NULL;
10503                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
10504                         rsurface.modelvertexmesh = NULL;
10505                         rsurface.modelvertexmeshbuffer = NULL;
10506                         rsurface.modelvertex3fbuffer = NULL;
10507                 }
10508                 rsurface.modelvertex3f_vertexbuffer = 0;
10509                 rsurface.modelvertex3f_bufferoffset = 0;
10510                 rsurface.modelsvector3f_vertexbuffer = 0;
10511                 rsurface.modelsvector3f_bufferoffset = 0;
10512                 rsurface.modeltvector3f_vertexbuffer = 0;
10513                 rsurface.modeltvector3f_bufferoffset = 0;
10514                 rsurface.modelnormal3f_vertexbuffer = 0;
10515                 rsurface.modelnormal3f_bufferoffset = 0;
10516                 rsurface.modelgeneratedvertex = true;
10517         }
10518         else
10519         {
10520                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10521                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10522                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10523                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10524                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10525                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10526                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10527                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10528                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10529                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10530                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10531                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10532                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10533                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10534                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10535                 rsurface.modelgeneratedvertex = false;
10536         }
10537         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10538         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10539         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10540         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10541         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10542         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10543         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10544         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10545         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10546         rsurface.modelelement3i = model->surfmesh.data_element3i;
10547         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10548         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10549         rsurface.modelelement3s = model->surfmesh.data_element3s;
10550         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10551         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10552         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10553         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10554         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10555         rsurface.modelsurfaces = model->data_surfaces;
10556         rsurface.batchgeneratedvertex = false;
10557         rsurface.batchfirstvertex = 0;
10558         rsurface.batchnumvertices = 0;
10559         rsurface.batchfirsttriangle = 0;
10560         rsurface.batchnumtriangles = 0;
10561         rsurface.batchvertex3f  = NULL;
10562         rsurface.batchvertex3f_vertexbuffer = NULL;
10563         rsurface.batchvertex3f_bufferoffset = 0;
10564         rsurface.batchsvector3f = NULL;
10565         rsurface.batchsvector3f_vertexbuffer = NULL;
10566         rsurface.batchsvector3f_bufferoffset = 0;
10567         rsurface.batchtvector3f = NULL;
10568         rsurface.batchtvector3f_vertexbuffer = NULL;
10569         rsurface.batchtvector3f_bufferoffset = 0;
10570         rsurface.batchnormal3f  = NULL;
10571         rsurface.batchnormal3f_vertexbuffer = NULL;
10572         rsurface.batchnormal3f_bufferoffset = 0;
10573         rsurface.batchlightmapcolor4f = NULL;
10574         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10575         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10576         rsurface.batchtexcoordtexture2f = NULL;
10577         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10578         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10579         rsurface.batchtexcoordlightmap2f = NULL;
10580         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10581         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10582         rsurface.batchvertexmesh = NULL;
10583         rsurface.batchvertexmeshbuffer = NULL;
10584         rsurface.batchvertex3fbuffer = NULL;
10585         rsurface.batchelement3i = NULL;
10586         rsurface.batchelement3i_indexbuffer = NULL;
10587         rsurface.batchelement3i_bufferoffset = 0;
10588         rsurface.batchelement3s = NULL;
10589         rsurface.batchelement3s_indexbuffer = NULL;
10590         rsurface.batchelement3s_bufferoffset = 0;
10591         rsurface.passcolor4f = NULL;
10592         rsurface.passcolor4f_vertexbuffer = NULL;
10593         rsurface.passcolor4f_bufferoffset = 0;
10594 }
10595
10596 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)
10597 {
10598         rsurface.entity = r_refdef.scene.worldentity;
10599         rsurface.skeleton = NULL;
10600         rsurface.ent_skinnum = 0;
10601         rsurface.ent_qwskin = -1;
10602         rsurface.ent_shadertime = shadertime;
10603         rsurface.ent_flags = entflags;
10604         rsurface.modelnumvertices = numvertices;
10605         rsurface.modelnumtriangles = numtriangles;
10606         rsurface.matrix = *matrix;
10607         rsurface.inversematrix = *inversematrix;
10608         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10609         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10610         R_EntityMatrix(&rsurface.matrix);
10611         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10612         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10613         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10614         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10615         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10616         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10617         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10618         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10619         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10620         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10621         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10622         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10623         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);
10624         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10625         rsurface.frameblend[0].lerp = 1;
10626         rsurface.ent_alttextures = false;
10627         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10628         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10629         if (wanttangents)
10630         {
10631                 rsurface.modelvertex3f = (float *)vertex3f;
10632                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10633                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10634                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10635         }
10636         else if (wantnormals)
10637         {
10638                 rsurface.modelvertex3f = (float *)vertex3f;
10639                 rsurface.modelsvector3f = NULL;
10640                 rsurface.modeltvector3f = NULL;
10641                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10642         }
10643         else
10644         {
10645                 rsurface.modelvertex3f = (float *)vertex3f;
10646                 rsurface.modelsvector3f = NULL;
10647                 rsurface.modeltvector3f = NULL;
10648                 rsurface.modelnormal3f = NULL;
10649         }
10650         rsurface.modelvertexmesh = NULL;
10651         rsurface.modelvertexmeshbuffer = NULL;
10652         rsurface.modelvertex3fbuffer = NULL;
10653         rsurface.modelvertex3f_vertexbuffer = 0;
10654         rsurface.modelvertex3f_bufferoffset = 0;
10655         rsurface.modelsvector3f_vertexbuffer = 0;
10656         rsurface.modelsvector3f_bufferoffset = 0;
10657         rsurface.modeltvector3f_vertexbuffer = 0;
10658         rsurface.modeltvector3f_bufferoffset = 0;
10659         rsurface.modelnormal3f_vertexbuffer = 0;
10660         rsurface.modelnormal3f_bufferoffset = 0;
10661         rsurface.modelgeneratedvertex = true;
10662         rsurface.modellightmapcolor4f  = (float *)color4f;
10663         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10664         rsurface.modellightmapcolor4f_bufferoffset = 0;
10665         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
10666         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10667         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10668         rsurface.modeltexcoordlightmap2f  = NULL;
10669         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10670         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10671         rsurface.modelelement3i = (int *)element3i;
10672         rsurface.modelelement3i_indexbuffer = NULL;
10673         rsurface.modelelement3i_bufferoffset = 0;
10674         rsurface.modelelement3s = (unsigned short *)element3s;
10675         rsurface.modelelement3s_indexbuffer = NULL;
10676         rsurface.modelelement3s_bufferoffset = 0;
10677         rsurface.modellightmapoffsets = NULL;
10678         rsurface.modelsurfaces = NULL;
10679         rsurface.batchgeneratedvertex = false;
10680         rsurface.batchfirstvertex = 0;
10681         rsurface.batchnumvertices = 0;
10682         rsurface.batchfirsttriangle = 0;
10683         rsurface.batchnumtriangles = 0;
10684         rsurface.batchvertex3f  = NULL;
10685         rsurface.batchvertex3f_vertexbuffer = NULL;
10686         rsurface.batchvertex3f_bufferoffset = 0;
10687         rsurface.batchsvector3f = NULL;
10688         rsurface.batchsvector3f_vertexbuffer = NULL;
10689         rsurface.batchsvector3f_bufferoffset = 0;
10690         rsurface.batchtvector3f = NULL;
10691         rsurface.batchtvector3f_vertexbuffer = NULL;
10692         rsurface.batchtvector3f_bufferoffset = 0;
10693         rsurface.batchnormal3f  = NULL;
10694         rsurface.batchnormal3f_vertexbuffer = NULL;
10695         rsurface.batchnormal3f_bufferoffset = 0;
10696         rsurface.batchlightmapcolor4f = NULL;
10697         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10698         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10699         rsurface.batchtexcoordtexture2f = NULL;
10700         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10701         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10702         rsurface.batchtexcoordlightmap2f = NULL;
10703         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10704         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10705         rsurface.batchvertexmesh = NULL;
10706         rsurface.batchvertexmeshbuffer = NULL;
10707         rsurface.batchvertex3fbuffer = NULL;
10708         rsurface.batchelement3i = NULL;
10709         rsurface.batchelement3i_indexbuffer = NULL;
10710         rsurface.batchelement3i_bufferoffset = 0;
10711         rsurface.batchelement3s = NULL;
10712         rsurface.batchelement3s_indexbuffer = NULL;
10713         rsurface.batchelement3s_bufferoffset = 0;
10714         rsurface.passcolor4f = NULL;
10715         rsurface.passcolor4f_vertexbuffer = NULL;
10716         rsurface.passcolor4f_bufferoffset = 0;
10717
10718         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10719         {
10720                 if ((wantnormals || wanttangents) && !normal3f)
10721                 {
10722                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10723                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10724                 }
10725                 if (wanttangents && !svector3f)
10726                 {
10727                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10728                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10729                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10730                 }
10731         }
10732 }
10733
10734 float RSurf_FogPoint(const float *v)
10735 {
10736         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10737         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10738         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10739         float FogHeightFade = r_refdef.fogheightfade;
10740         float fogfrac;
10741         unsigned int fogmasktableindex;
10742         if (r_refdef.fogplaneviewabove)
10743                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10744         else
10745                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10746         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10747         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10748 }
10749
10750 float RSurf_FogVertex(const float *v)
10751 {
10752         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10753         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10754         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10755         float FogHeightFade = rsurface.fogheightfade;
10756         float fogfrac;
10757         unsigned int fogmasktableindex;
10758         if (r_refdef.fogplaneviewabove)
10759                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10760         else
10761                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10762         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10763         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10764 }
10765
10766 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10767 {
10768         int i;
10769         for (i = 0;i < numelements;i++)
10770                 outelement3i[i] = inelement3i[i] + adjust;
10771 }
10772
10773 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10774 extern cvar_t gl_vbo;
10775 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10776 {
10777         int deformindex;
10778         int firsttriangle;
10779         int numtriangles;
10780         int firstvertex;
10781         int endvertex;
10782         int numvertices;
10783         int surfacefirsttriangle;
10784         int surfacenumtriangles;
10785         int surfacefirstvertex;
10786         int surfaceendvertex;
10787         int surfacenumvertices;
10788         int batchnumvertices;
10789         int batchnumtriangles;
10790         int needsupdate;
10791         int i, j;
10792         qboolean gaps;
10793         qboolean dynamicvertex;
10794         float amplitude;
10795         float animpos;
10796         float scale;
10797         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10798         float waveparms[4];
10799         q3shaderinfo_deform_t *deform;
10800         const msurface_t *surface, *firstsurface;
10801         r_vertexmesh_t *vertexmesh;
10802         if (!texturenumsurfaces)
10803                 return;
10804         // find vertex range of this surface batch
10805         gaps = false;
10806         firstsurface = texturesurfacelist[0];
10807         firsttriangle = firstsurface->num_firsttriangle;
10808         batchnumvertices = 0;
10809         batchnumtriangles = 0;
10810         firstvertex = endvertex = firstsurface->num_firstvertex;
10811         for (i = 0;i < texturenumsurfaces;i++)
10812         {
10813                 surface = texturesurfacelist[i];
10814                 if (surface != firstsurface + i)
10815                         gaps = true;
10816                 surfacefirstvertex = surface->num_firstvertex;
10817                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10818                 surfacenumvertices = surface->num_vertices;
10819                 surfacenumtriangles = surface->num_triangles;
10820                 if (firstvertex > surfacefirstvertex)
10821                         firstvertex = surfacefirstvertex;
10822                 if (endvertex < surfaceendvertex)
10823                         endvertex = surfaceendvertex;
10824                 batchnumvertices += surfacenumvertices;
10825                 batchnumtriangles += surfacenumtriangles;
10826         }
10827
10828         // we now know the vertex range used, and if there are any gaps in it
10829         rsurface.batchfirstvertex = firstvertex;
10830         rsurface.batchnumvertices = endvertex - firstvertex;
10831         rsurface.batchfirsttriangle = firsttriangle;
10832         rsurface.batchnumtriangles = batchnumtriangles;
10833
10834         // this variable holds flags for which properties have been updated that
10835         // may require regenerating vertexmesh array...
10836         needsupdate = 0;
10837
10838         // check if any dynamic vertex processing must occur
10839         dynamicvertex = false;
10840
10841         // if there is a chance of animated vertex colors, it's a dynamic batch
10842         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10843         {
10844                 dynamicvertex = true;
10845                 batchneed |= BATCHNEED_NOGAPS;
10846                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
10847         }
10848
10849         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10850         {
10851                 switch (deform->deform)
10852                 {
10853                 default:
10854                 case Q3DEFORM_PROJECTIONSHADOW:
10855                 case Q3DEFORM_TEXT0:
10856                 case Q3DEFORM_TEXT1:
10857                 case Q3DEFORM_TEXT2:
10858                 case Q3DEFORM_TEXT3:
10859                 case Q3DEFORM_TEXT4:
10860                 case Q3DEFORM_TEXT5:
10861                 case Q3DEFORM_TEXT6:
10862                 case Q3DEFORM_TEXT7:
10863                 case Q3DEFORM_NONE:
10864                         break;
10865                 case Q3DEFORM_AUTOSPRITE:
10866                         dynamicvertex = true;
10867                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10868                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10869                         break;
10870                 case Q3DEFORM_AUTOSPRITE2:
10871                         dynamicvertex = true;
10872                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10873                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10874                         break;
10875                 case Q3DEFORM_NORMAL:
10876                         dynamicvertex = true;
10877                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10878                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10879                         break;
10880                 case Q3DEFORM_WAVE:
10881                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10882                                 break; // if wavefunc is a nop, ignore this transform
10883                         dynamicvertex = true;
10884                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10885                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10886                         break;
10887                 case Q3DEFORM_BULGE:
10888                         dynamicvertex = true;
10889                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10890                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10891                         break;
10892                 case Q3DEFORM_MOVE:
10893                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10894                                 break; // if wavefunc is a nop, ignore this transform
10895                         dynamicvertex = true;
10896                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10897                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
10898                         break;
10899                 }
10900         }
10901         switch(rsurface.texture->tcgen.tcgen)
10902         {
10903         default:
10904         case Q3TCGEN_TEXTURE:
10905                 break;
10906         case Q3TCGEN_LIGHTMAP:
10907                 dynamicvertex = true;
10908                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10909                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10910                 break;
10911         case Q3TCGEN_VECTOR:
10912                 dynamicvertex = true;
10913                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10914                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10915                 break;
10916         case Q3TCGEN_ENVIRONMENT:
10917                 dynamicvertex = true;
10918                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
10919                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10920                 break;
10921         }
10922         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10923         {
10924                 dynamicvertex = true;
10925                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10926                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10927         }
10928
10929         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10930         {
10931                 dynamicvertex = true;
10932                 batchneed |= BATCHNEED_NOGAPS;
10933                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
10934         }
10935
10936         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
10937         {
10938                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
10939                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
10940                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
10941                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
10942                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
10943                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
10944                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
10945         }
10946
10947         // when the model data has no vertex buffer (dynamic mesh), we need to
10948         // eliminate gaps
10949         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
10950                 batchneed |= BATCHNEED_NOGAPS;
10951
10952         // if needsupdate, we have to do a dynamic vertex batch for sure
10953         if (needsupdate & batchneed)
10954                 dynamicvertex = true;
10955
10956         // see if we need to build vertexmesh from arrays
10957         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10958                 dynamicvertex = true;
10959
10960         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
10961         // also some drivers strongly dislike firstvertex
10962         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
10963                 dynamicvertex = true;
10964
10965         rsurface.batchvertex3f = rsurface.modelvertex3f;
10966         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
10967         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10968         rsurface.batchsvector3f = rsurface.modelsvector3f;
10969         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
10970         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10971         rsurface.batchtvector3f = rsurface.modeltvector3f;
10972         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
10973         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10974         rsurface.batchnormal3f = rsurface.modelnormal3f;
10975         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
10976         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10977         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
10978         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
10979         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
10980         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
10981         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
10982         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10983         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10984         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
10985         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10986         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
10987         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
10988         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
10989         rsurface.batchelement3i = rsurface.modelelement3i;
10990         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
10991         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
10992         rsurface.batchelement3s = rsurface.modelelement3s;
10993         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
10994         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
10995
10996         // if any dynamic vertex processing has to occur in software, we copy the
10997         // entire surface list together before processing to rebase the vertices
10998         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
10999         //
11000         // if any gaps exist and we do not have a static vertex buffer, we have to
11001         // copy the surface list together to avoid wasting upload bandwidth on the
11002         // vertices in the gaps.
11003         //
11004         // if gaps exist and we have a static vertex buffer, we still have to
11005         // combine the index buffer ranges into one dynamic index buffer.
11006         //
11007         // in all cases we end up with data that can be drawn in one call.
11008
11009         if (!dynamicvertex)
11010         {
11011                 // static vertex data, just set pointers...
11012                 rsurface.batchgeneratedvertex = false;
11013                 // if there are gaps, we want to build a combined index buffer,
11014                 // otherwise use the original static buffer with an appropriate offset
11015                 if (gaps)
11016                 {
11017                         // build a new triangle elements array for this batch
11018                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11019                         rsurface.batchfirsttriangle = 0;
11020                         numtriangles = 0;
11021                         for (i = 0;i < texturenumsurfaces;i++)
11022                         {
11023                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11024                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11025                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11026                                 numtriangles += surfacenumtriangles;
11027                         }
11028                         rsurface.batchelement3i_indexbuffer = NULL;
11029                         rsurface.batchelement3i_bufferoffset = 0;
11030                         rsurface.batchelement3s = NULL;
11031                         rsurface.batchelement3s_indexbuffer = NULL;
11032                         rsurface.batchelement3s_bufferoffset = 0;
11033                         if (endvertex <= 65536)
11034                         {
11035                                 // make a 16bit (unsigned short) index array if possible
11036                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11037                                 for (i = 0;i < numtriangles*3;i++)
11038                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11039                         }
11040                 }
11041                 return;
11042         }
11043
11044         // something needs software processing, do it for real...
11045         // we only directly handle separate array data in this case and then
11046         // generate interleaved data if needed...
11047         rsurface.batchgeneratedvertex = true;
11048
11049         // now copy the vertex data into a combined array and make an index array
11050         // (this is what Quake3 does all the time)
11051         //if (gaps || rsurface.batchfirstvertex)
11052         {
11053                 rsurface.batchvertex3fbuffer = NULL;
11054                 rsurface.batchvertexmesh = NULL;
11055                 rsurface.batchvertexmeshbuffer = NULL;
11056                 rsurface.batchvertex3f = NULL;
11057                 rsurface.batchvertex3f_vertexbuffer = NULL;
11058                 rsurface.batchvertex3f_bufferoffset = 0;
11059                 rsurface.batchsvector3f = NULL;
11060                 rsurface.batchsvector3f_vertexbuffer = NULL;
11061                 rsurface.batchsvector3f_bufferoffset = 0;
11062                 rsurface.batchtvector3f = NULL;
11063                 rsurface.batchtvector3f_vertexbuffer = NULL;
11064                 rsurface.batchtvector3f_bufferoffset = 0;
11065                 rsurface.batchnormal3f = NULL;
11066                 rsurface.batchnormal3f_vertexbuffer = NULL;
11067                 rsurface.batchnormal3f_bufferoffset = 0;
11068                 rsurface.batchlightmapcolor4f = NULL;
11069                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11070                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11071                 rsurface.batchtexcoordtexture2f = NULL;
11072                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11073                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11074                 rsurface.batchtexcoordlightmap2f = NULL;
11075                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11076                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11077                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11078                 rsurface.batchelement3i_indexbuffer = NULL;
11079                 rsurface.batchelement3i_bufferoffset = 0;
11080                 rsurface.batchelement3s = NULL;
11081                 rsurface.batchelement3s_indexbuffer = NULL;
11082                 rsurface.batchelement3s_bufferoffset = 0;
11083                 // we'll only be setting up certain arrays as needed
11084                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11085                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11086                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11087                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11088                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11089                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11090                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11091                 {
11092                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11093                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11094                 }
11095                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11096                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11097                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11098                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11099                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11100                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11101                 numvertices = 0;
11102                 numtriangles = 0;
11103                 for (i = 0;i < texturenumsurfaces;i++)
11104                 {
11105                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11106                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11107                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11108                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11109                         // copy only the data requested
11110                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11111                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11112                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11113                         {
11114                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11115                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11116                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11117                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11118                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11119                                 {
11120                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11121                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11122                                 }
11123                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11124                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11125                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11126                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11127                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11128                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11129                         }
11130                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11131                         numvertices += surfacenumvertices;
11132                         numtriangles += surfacenumtriangles;
11133                 }
11134
11135                 // generate a 16bit index array as well if possible
11136                 // (in general, dynamic batches fit)
11137                 if (numvertices <= 65536)
11138                 {
11139                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11140                         for (i = 0;i < numtriangles*3;i++)
11141                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11142                 }
11143
11144                 // since we've copied everything, the batch now starts at 0
11145                 rsurface.batchfirstvertex = 0;
11146                 rsurface.batchnumvertices = batchnumvertices;
11147                 rsurface.batchfirsttriangle = 0;
11148                 rsurface.batchnumtriangles = batchnumtriangles;
11149         }
11150
11151         // q1bsp surfaces rendered in vertex color mode have to have colors
11152         // calculated based on lightstyles
11153         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11154         {
11155                 // generate color arrays for the surfaces in this list
11156                 int c[4];
11157                 int scale;
11158                 int size3;
11159                 const int *offsets;
11160                 const unsigned char *lm;
11161                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11162                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11163                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11164                 numvertices = 0;
11165                 for (i = 0;i < texturenumsurfaces;i++)
11166                 {
11167                         surface = texturesurfacelist[i];
11168                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11169                         surfacenumvertices = surface->num_vertices;
11170                         if (surface->lightmapinfo->samples)
11171                         {
11172                                 for (j = 0;j < surfacenumvertices;j++)
11173                                 {
11174                                         lm = surface->lightmapinfo->samples + offsets[j];
11175                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11176                                         VectorScale(lm, scale, c);
11177                                         if (surface->lightmapinfo->styles[1] != 255)
11178                                         {
11179                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11180                                                 lm += size3;
11181                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11182                                                 VectorMA(c, scale, lm, c);
11183                                                 if (surface->lightmapinfo->styles[2] != 255)
11184                                                 {
11185                                                         lm += size3;
11186                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11187                                                         VectorMA(c, scale, lm, c);
11188                                                         if (surface->lightmapinfo->styles[3] != 255)
11189                                                         {
11190                                                                 lm += size3;
11191                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11192                                                                 VectorMA(c, scale, lm, c);
11193                                                         }
11194                                                 }
11195                                         }
11196                                         c[0] >>= 7;
11197                                         c[1] >>= 7;
11198                                         c[2] >>= 7;
11199                                         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);
11200                                         numvertices++;
11201                                 }
11202                         }
11203                         else
11204                         {
11205                                 for (j = 0;j < surfacenumvertices;j++)
11206                                 {
11207                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11208                                         numvertices++;
11209                                 }
11210                         }
11211                 }
11212         }
11213
11214         // if vertices are deformed (sprite flares and things in maps, possibly
11215         // water waves, bulges and other deformations), modify the copied vertices
11216         // in place
11217         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11218         {
11219                 switch (deform->deform)
11220                 {
11221                 default:
11222                 case Q3DEFORM_PROJECTIONSHADOW:
11223                 case Q3DEFORM_TEXT0:
11224                 case Q3DEFORM_TEXT1:
11225                 case Q3DEFORM_TEXT2:
11226                 case Q3DEFORM_TEXT3:
11227                 case Q3DEFORM_TEXT4:
11228                 case Q3DEFORM_TEXT5:
11229                 case Q3DEFORM_TEXT6:
11230                 case Q3DEFORM_TEXT7:
11231                 case Q3DEFORM_NONE:
11232                         break;
11233                 case Q3DEFORM_AUTOSPRITE:
11234                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11235                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11236                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11237                         VectorNormalize(newforward);
11238                         VectorNormalize(newright);
11239                         VectorNormalize(newup);
11240 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11241 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11242 //                      rsurface.batchvertex3f_bufferoffset = 0;
11243 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11244 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
11245 //                      rsurface.batchsvector3f_bufferoffset = 0;
11246 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11247 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
11248 //                      rsurface.batchtvector3f_bufferoffset = 0;
11249 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11250 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11251 //                      rsurface.batchnormal3f_bufferoffset = 0;
11252                         // a single autosprite surface can contain multiple sprites...
11253                         for (j = 0;j < batchnumvertices - 3;j += 4)
11254                         {
11255                                 VectorClear(center);
11256                                 for (i = 0;i < 4;i++)
11257                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11258                                 VectorScale(center, 0.25f, center);
11259                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11260                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11261                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11262                                 for (i = 0;i < 4;i++)
11263                                 {
11264                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11265                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11266                                 }
11267                         }
11268                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11269                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11270                         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);
11271                         break;
11272                 case Q3DEFORM_AUTOSPRITE2:
11273                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11274                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11275                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11276                         VectorNormalize(newforward);
11277                         VectorNormalize(newright);
11278                         VectorNormalize(newup);
11279 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11280 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11281 //                      rsurface.batchvertex3f_bufferoffset = 0;
11282                         {
11283                                 const float *v1, *v2;
11284                                 vec3_t start, end;
11285                                 float f, l;
11286                                 struct
11287                                 {
11288                                         float length2;
11289                                         const float *v1;
11290                                         const float *v2;
11291                                 }
11292                                 shortest[2];
11293                                 memset(shortest, 0, sizeof(shortest));
11294                                 // a single autosprite surface can contain multiple sprites...
11295                                 for (j = 0;j < batchnumvertices - 3;j += 4)
11296                                 {
11297                                         VectorClear(center);
11298                                         for (i = 0;i < 4;i++)
11299                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11300                                         VectorScale(center, 0.25f, center);
11301                                         // find the two shortest edges, then use them to define the
11302                                         // axis vectors for rotating around the central axis
11303                                         for (i = 0;i < 6;i++)
11304                                         {
11305                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11306                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11307                                                 l = VectorDistance2(v1, v2);
11308                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11309                                                 if (v1[2] != v2[2])
11310                                                         l += (1.0f / 1024.0f);
11311                                                 if (shortest[0].length2 > l || i == 0)
11312                                                 {
11313                                                         shortest[1] = shortest[0];
11314                                                         shortest[0].length2 = l;
11315                                                         shortest[0].v1 = v1;
11316                                                         shortest[0].v2 = v2;
11317                                                 }
11318                                                 else if (shortest[1].length2 > l || i == 1)
11319                                                 {
11320                                                         shortest[1].length2 = l;
11321                                                         shortest[1].v1 = v1;
11322                                                         shortest[1].v2 = v2;
11323                                                 }
11324                                         }
11325                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11326                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11327                                         // this calculates the right vector from the shortest edge
11328                                         // and the up vector from the edge midpoints
11329                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11330                                         VectorNormalize(right);
11331                                         VectorSubtract(end, start, up);
11332                                         VectorNormalize(up);
11333                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11334                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11335                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11336                                         VectorNegate(forward, forward);
11337                                         VectorReflect(forward, 0, up, forward);
11338                                         VectorNormalize(forward);
11339                                         CrossProduct(up, forward, newright);
11340                                         VectorNormalize(newright);
11341                                         // rotate the quad around the up axis vector, this is made
11342                                         // especially easy by the fact we know the quad is flat,
11343                                         // so we only have to subtract the center position and
11344                                         // measure distance along the right vector, and then
11345                                         // multiply that by the newright vector and add back the
11346                                         // center position
11347                                         // we also need to subtract the old position to undo the
11348                                         // displacement from the center, which we do with a
11349                                         // DotProduct, the subtraction/addition of center is also
11350                                         // optimized into DotProducts here
11351                                         l = DotProduct(right, center);
11352                                         for (i = 0;i < 4;i++)
11353                                         {
11354                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11355                                                 f = DotProduct(right, v1) - l;
11356                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11357                                         }
11358                                 }
11359                         }
11360                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11361                         {
11362 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11363 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
11364 //                              rsurface.batchnormal3f_bufferoffset = 0;
11365                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11366                         }
11367                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11368                         {
11369 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11370 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11371 //                              rsurface.batchsvector3f_bufferoffset = 0;
11372 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11373 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11374 //                              rsurface.batchtvector3f_bufferoffset = 0;
11375                                 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);
11376                         }
11377                         break;
11378                 case Q3DEFORM_NORMAL:
11379                         // deform the normals to make reflections wavey
11380                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11381                         rsurface.batchnormal3f_vertexbuffer = NULL;
11382                         rsurface.batchnormal3f_bufferoffset = 0;
11383                         for (j = 0;j < batchnumvertices;j++)
11384                         {
11385                                 float vertex[3];
11386                                 float *normal = rsurface.batchnormal3f + 3*j;
11387                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11388                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11389                                 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]);
11390                                 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]);
11391                                 VectorNormalize(normal);
11392                         }
11393                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11394                         {
11395 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11396 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11397 //                              rsurface.batchsvector3f_bufferoffset = 0;
11398 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11399 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11400 //                              rsurface.batchtvector3f_bufferoffset = 0;
11401                                 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);
11402                         }
11403                         break;
11404                 case Q3DEFORM_WAVE:
11405                         // deform vertex array to make wavey water and flags and such
11406                         waveparms[0] = deform->waveparms[0];
11407                         waveparms[1] = deform->waveparms[1];
11408                         waveparms[2] = deform->waveparms[2];
11409                         waveparms[3] = deform->waveparms[3];
11410                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11411                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11412                         // this is how a divisor of vertex influence on deformation
11413                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11414                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11415 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11416 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11417 //                      rsurface.batchvertex3f_bufferoffset = 0;
11418 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11419 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11420 //                      rsurface.batchnormal3f_bufferoffset = 0;
11421                         for (j = 0;j < batchnumvertices;j++)
11422                         {
11423                                 // if the wavefunc depends on time, evaluate it per-vertex
11424                                 if (waveparms[3])
11425                                 {
11426                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11427                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11428                                 }
11429                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11430                         }
11431                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11432                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11433                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11434                         {
11435 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11436 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11437 //                              rsurface.batchsvector3f_bufferoffset = 0;
11438 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11439 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11440 //                              rsurface.batchtvector3f_bufferoffset = 0;
11441                                 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);
11442                         }
11443                         break;
11444                 case Q3DEFORM_BULGE:
11445                         // deform vertex array to make the surface have moving bulges
11446 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11447 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11448 //                      rsurface.batchvertex3f_bufferoffset = 0;
11449 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11450 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11451 //                      rsurface.batchnormal3f_bufferoffset = 0;
11452                         for (j = 0;j < batchnumvertices;j++)
11453                         {
11454                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11455                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11456                         }
11457                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11458                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11459                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11460                         {
11461 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11462 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11463 //                              rsurface.batchsvector3f_bufferoffset = 0;
11464 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11465 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11466 //                              rsurface.batchtvector3f_bufferoffset = 0;
11467                                 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);
11468                         }
11469                         break;
11470                 case Q3DEFORM_MOVE:
11471                         // deform vertex array
11472                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11473                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11474                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11475                         VectorScale(deform->parms, scale, waveparms);
11476 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11477 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11478 //                      rsurface.batchvertex3f_bufferoffset = 0;
11479                         for (j = 0;j < batchnumvertices;j++)
11480                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
11481                         break;
11482                 }
11483         }
11484
11485         // generate texcoords based on the chosen texcoord source
11486         switch(rsurface.texture->tcgen.tcgen)
11487         {
11488         default:
11489         case Q3TCGEN_TEXTURE:
11490                 break;
11491         case Q3TCGEN_LIGHTMAP:
11492 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11493 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11494 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11495                 if (rsurface.batchtexcoordlightmap2f)
11496                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
11497                 break;
11498         case Q3TCGEN_VECTOR:
11499 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11500 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11501 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11502                 for (j = 0;j < batchnumvertices;j++)
11503                 {
11504                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11505                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11506                 }
11507                 break;
11508         case Q3TCGEN_ENVIRONMENT:
11509                 // make environment reflections using a spheremap
11510                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11511                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11512                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11513                 for (j = 0;j < batchnumvertices;j++)
11514                 {
11515                         // identical to Q3A's method, but executed in worldspace so
11516                         // carried models can be shiny too
11517
11518                         float viewer[3], d, reflected[3], worldreflected[3];
11519
11520                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11521                         // VectorNormalize(viewer);
11522
11523                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11524
11525                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11526                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11527                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11528                         // note: this is proportinal to viewer, so we can normalize later
11529
11530                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11531                         VectorNormalize(worldreflected);
11532
11533                         // note: this sphere map only uses world x and z!
11534                         // so positive and negative y will LOOK THE SAME.
11535                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11536                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11537                 }
11538                 break;
11539         }
11540         // the only tcmod that needs software vertex processing is turbulent, so
11541         // check for it here and apply the changes if needed
11542         // and we only support that as the first one
11543         // (handling a mixture of turbulent and other tcmods would be problematic
11544         //  without punting it entirely to a software path)
11545         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11546         {
11547                 amplitude = rsurface.texture->tcmods[0].parms[1];
11548                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11549 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11550 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11551 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11552                 for (j = 0;j < batchnumvertices;j++)
11553                 {
11554                         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);
11555                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11556                 }
11557         }
11558
11559         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11560         {
11561                 // convert the modified arrays to vertex structs
11562 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11563 //              rsurface.batchvertexmeshbuffer = NULL;
11564                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11565                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11566                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11567                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11568                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11569                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11570                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11571                 {
11572                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11573                         {
11574                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11575                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11576                         }
11577                 }
11578                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11579                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11580                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11581                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11582                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11583                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11584                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11585                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11586                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11587         }
11588 }
11589
11590 void RSurf_DrawBatch(void)
11591 {
11592         // sometimes a zero triangle surface (usually a degenerate patch) makes it
11593         // through the pipeline, killing it earlier in the pipeline would have
11594         // per-surface overhead rather than per-batch overhead, so it's best to
11595         // reject it here, before it hits glDraw.
11596         if (rsurface.batchnumtriangles == 0)
11597                 return;
11598 #if 0
11599         // batch debugging code
11600         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
11601         {
11602                 int i;
11603                 int j;
11604                 int c;
11605                 const int *e;
11606                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
11607                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
11608                 {
11609                         c = e[i];
11610                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
11611                         {
11612                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
11613                                 {
11614                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
11615                                                 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);
11616                                         break;
11617                                 }
11618                         }
11619                 }
11620         }
11621 #endif
11622         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);
11623 }
11624
11625 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11626 {
11627         // pick the closest matching water plane
11628         int planeindex, vertexindex, bestplaneindex = -1;
11629         float d, bestd;
11630         vec3_t vert;
11631         const float *v;
11632         r_waterstate_waterplane_t *p;
11633         qboolean prepared = false;
11634         bestd = 0;
11635         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11636         {
11637                 if(p->camera_entity != rsurface.texture->camera_entity)
11638                         continue;
11639                 d = 0;
11640                 if(!prepared)
11641                 {
11642                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11643                         prepared = true;
11644                         if(rsurface.batchnumvertices == 0)
11645                                 break;
11646                 }
11647                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11648                 {
11649                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11650                         d += fabs(PlaneDiff(vert, &p->plane));
11651                 }
11652                 if (bestd > d || bestplaneindex < 0)
11653                 {
11654                         bestd = d;
11655                         bestplaneindex = planeindex;
11656                 }
11657         }
11658         return bestplaneindex;
11659         // NOTE: this MAY return a totally unrelated water plane; we can ignore
11660         // this situation though, as it might be better to render single larger
11661         // batches with useless stuff (backface culled for example) than to
11662         // render multiple smaller batches
11663 }
11664
11665 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11666 {
11667         int i;
11668         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11669         rsurface.passcolor4f_vertexbuffer = 0;
11670         rsurface.passcolor4f_bufferoffset = 0;
11671         for (i = 0;i < rsurface.batchnumvertices;i++)
11672                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11673 }
11674
11675 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11676 {
11677         int i;
11678         float f;
11679         const float *v;
11680         const float *c;
11681         float *c2;
11682         if (rsurface.passcolor4f)
11683         {
11684                 // generate color arrays
11685                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11686                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11687                 rsurface.passcolor4f_vertexbuffer = 0;
11688                 rsurface.passcolor4f_bufferoffset = 0;
11689                 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)
11690                 {
11691                         f = RSurf_FogVertex(v);
11692                         c2[0] = c[0] * f;
11693                         c2[1] = c[1] * f;
11694                         c2[2] = c[2] * f;
11695                         c2[3] = c[3];
11696                 }
11697         }
11698         else
11699         {
11700                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11701                 rsurface.passcolor4f_vertexbuffer = 0;
11702                 rsurface.passcolor4f_bufferoffset = 0;
11703                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11704                 {
11705                         f = RSurf_FogVertex(v);
11706                         c2[0] = f;
11707                         c2[1] = f;
11708                         c2[2] = f;
11709                         c2[3] = 1;
11710                 }
11711         }
11712 }
11713
11714 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11715 {
11716         int i;
11717         float f;
11718         const float *v;
11719         const float *c;
11720         float *c2;
11721         if (!rsurface.passcolor4f)
11722                 return;
11723         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11724         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11725         rsurface.passcolor4f_vertexbuffer = 0;
11726         rsurface.passcolor4f_bufferoffset = 0;
11727         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)
11728         {
11729                 f = RSurf_FogVertex(v);
11730                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11731                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11732                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11733                 c2[3] = c[3];
11734         }
11735 }
11736
11737 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11738 {
11739         int i;
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, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11749         {
11750                 c2[0] = c[0] * r;
11751                 c2[1] = c[1] * g;
11752                 c2[2] = c[2] * b;
11753                 c2[3] = c[3] * a;
11754         }
11755 }
11756
11757 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11758 {
11759         int i;
11760         const float *c;
11761         float *c2;
11762         if (!rsurface.passcolor4f)
11763                 return;
11764         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11765         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11766         rsurface.passcolor4f_vertexbuffer = 0;
11767         rsurface.passcolor4f_bufferoffset = 0;
11768         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11769         {
11770                 c2[0] = c[0] + r_refdef.scene.ambient;
11771                 c2[1] = c[1] + r_refdef.scene.ambient;
11772                 c2[2] = c[2] + r_refdef.scene.ambient;
11773                 c2[3] = c[3];
11774         }
11775 }
11776
11777 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11778 {
11779         // TODO: optimize
11780         rsurface.passcolor4f = NULL;
11781         rsurface.passcolor4f_vertexbuffer = 0;
11782         rsurface.passcolor4f_bufferoffset = 0;
11783         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11784         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11785         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11786         GL_Color(r, g, b, a);
11787         R_Mesh_TexBind(0, rsurface.lightmaptexture);
11788         RSurf_DrawBatch();
11789 }
11790
11791 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11792 {
11793         // TODO: optimize applyfog && applycolor case
11794         // just apply fog if necessary, and tint the fog color array if necessary
11795         rsurface.passcolor4f = NULL;
11796         rsurface.passcolor4f_vertexbuffer = 0;
11797         rsurface.passcolor4f_bufferoffset = 0;
11798         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11799         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11800         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11801         GL_Color(r, g, b, a);
11802         RSurf_DrawBatch();
11803 }
11804
11805 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11806 {
11807         // TODO: optimize
11808         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11809         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11810         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11811         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11812         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11813         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11814         GL_Color(r, g, b, a);
11815         RSurf_DrawBatch();
11816 }
11817
11818 static void RSurf_DrawBatch_GL11_ClampColor(void)
11819 {
11820         int i;
11821         const float *c1;
11822         float *c2;
11823         if (!rsurface.passcolor4f)
11824                 return;
11825         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11826         {
11827                 c2[0] = bound(0.0f, c1[0], 1.0f);
11828                 c2[1] = bound(0.0f, c1[1], 1.0f);
11829                 c2[2] = bound(0.0f, c1[2], 1.0f);
11830                 c2[3] = bound(0.0f, c1[3], 1.0f);
11831         }
11832 }
11833
11834 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
11835 {
11836         int i;
11837         float f;
11838         const float *v;
11839         const float *n;
11840         float *c;
11841         //vec3_t eyedir;
11842
11843         // fake shading
11844         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11845         rsurface.passcolor4f_vertexbuffer = 0;
11846         rsurface.passcolor4f_bufferoffset = 0;
11847         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)
11848         {
11849                 f = -DotProduct(r_refdef.view.forward, n);
11850                 f = max(0, f);
11851                 f = f * 0.85 + 0.15; // work around so stuff won't get black
11852                 f *= r_refdef.lightmapintensity;
11853                 Vector4Set(c, f, f, f, 1);
11854         }
11855 }
11856
11857 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11858 {
11859         RSurf_DrawBatch_GL11_ApplyFakeLight();
11860         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11861         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11862         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11863         GL_Color(r, g, b, a);
11864         RSurf_DrawBatch();
11865 }
11866
11867 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11868 {
11869         int i;
11870         float f;
11871         float alpha;
11872         const float *v;
11873         const float *n;
11874         float *c;
11875         vec3_t ambientcolor;
11876         vec3_t diffusecolor;
11877         vec3_t lightdir;
11878         // TODO: optimize
11879         // model lighting
11880         VectorCopy(rsurface.modellight_lightdir, lightdir);
11881         f = 0.5f * r_refdef.lightmapintensity;
11882         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11883         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11884         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11885         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11886         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11887         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11888         alpha = *a;
11889         if (VectorLength2(diffusecolor) > 0)
11890         {
11891                 // q3-style directional shading
11892                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11893                 rsurface.passcolor4f_vertexbuffer = 0;
11894                 rsurface.passcolor4f_bufferoffset = 0;
11895                 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)
11896                 {
11897                         if ((f = DotProduct(n, lightdir)) > 0)
11898                                 VectorMA(ambientcolor, f, diffusecolor, c);
11899                         else
11900                                 VectorCopy(ambientcolor, c);
11901                         c[3] = alpha;
11902                 }
11903                 *r = 1;
11904                 *g = 1;
11905                 *b = 1;
11906                 *a = 1;
11907                 *applycolor = false;
11908         }
11909         else
11910         {
11911                 *r = ambientcolor[0];
11912                 *g = ambientcolor[1];
11913                 *b = ambientcolor[2];
11914                 rsurface.passcolor4f = NULL;
11915                 rsurface.passcolor4f_vertexbuffer = 0;
11916                 rsurface.passcolor4f_bufferoffset = 0;
11917         }
11918 }
11919
11920 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11921 {
11922         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
11923         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11924         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11925         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11926         GL_Color(r, g, b, a);
11927         RSurf_DrawBatch();
11928 }
11929
11930 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
11931 {
11932         int i;
11933         float f;
11934         const float *v;
11935         float *c;
11936         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
11937         {
11938                 f = 1 - RSurf_FogVertex(v);
11939                 c[0] = r;
11940                 c[1] = g;
11941                 c[2] = b;
11942                 c[3] = f * a;
11943         }
11944 }
11945
11946 void RSurf_SetupDepthAndCulling(void)
11947 {
11948         // submodels are biased to avoid z-fighting with world surfaces that they
11949         // may be exactly overlapping (avoids z-fighting artifacts on certain
11950         // doors and things in Quake maps)
11951         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11952         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11953         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11954         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11955 }
11956
11957 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11958 {
11959         // transparent sky would be ridiculous
11960         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11961                 return;
11962         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11963         skyrenderlater = true;
11964         RSurf_SetupDepthAndCulling();
11965         GL_DepthMask(true);
11966         // LordHavoc: HalfLife maps have freaky skypolys so don't use
11967         // skymasking on them, and Quake3 never did sky masking (unlike
11968         // software Quake and software Quake2), so disable the sky masking
11969         // in Quake3 maps as it causes problems with q3map2 sky tricks,
11970         // and skymasking also looks very bad when noclipping outside the
11971         // level, so don't use it then either.
11972         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
11973         {
11974                 R_Mesh_ResetTextureState();
11975                 if (skyrendermasked)
11976                 {
11977                         R_SetupShader_DepthOrShadow();
11978                         // depth-only (masking)
11979                         GL_ColorMask(0,0,0,0);
11980                         // just to make sure that braindead drivers don't draw
11981                         // anything despite that colormask...
11982                         GL_BlendFunc(GL_ZERO, GL_ONE);
11983                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11984                         if (rsurface.batchvertex3fbuffer)
11985                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
11986                         else
11987                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
11988                 }
11989                 else
11990                 {
11991                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11992                         // fog sky
11993                         GL_BlendFunc(GL_ONE, GL_ZERO);
11994                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11995                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
11996                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11997                 }
11998                 RSurf_DrawBatch();
11999                 if (skyrendermasked)
12000                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12001         }
12002         R_Mesh_ResetTextureState();
12003         GL_Color(1, 1, 1, 1);
12004 }
12005
12006 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12007 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12008 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12009 {
12010         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12011                 return;
12012         if (prepass)
12013         {
12014                 // render screenspace normalmap to texture
12015                 GL_DepthMask(true);
12016                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12017                 RSurf_DrawBatch();
12018                 return;
12019         }
12020
12021         // bind lightmap texture
12022
12023         // water/refraction/reflection/camera surfaces have to be handled specially
12024         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12025         {
12026                 int start, end, startplaneindex;
12027                 for (start = 0;start < texturenumsurfaces;start = end)
12028                 {
12029                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12030                         if(startplaneindex < 0)
12031                         {
12032                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12033                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12034                                 end = start + 1;
12035                                 continue;
12036                         }
12037                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12038                                 ;
12039                         // now that we have a batch using the same planeindex, render it
12040                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12041                         {
12042                                 // render water or distortion background
12043                                 GL_DepthMask(true);
12044                                 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));
12045                                 RSurf_DrawBatch();
12046                                 // blend surface on top
12047                                 GL_DepthMask(false);
12048                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12049                                 RSurf_DrawBatch();
12050                         }
12051                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12052                         {
12053                                 // render surface with reflection texture as input
12054                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12055                                 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));
12056                                 RSurf_DrawBatch();
12057                         }
12058                 }
12059                 return;
12060         }
12061
12062         // render surface batch normally
12063         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12064         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12065         RSurf_DrawBatch();
12066 }
12067
12068 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12069 {
12070         // OpenGL 1.3 path - anything not completely ancient
12071         qboolean applycolor;
12072         qboolean applyfog;
12073         int layerindex;
12074         const texturelayer_t *layer;
12075         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);
12076         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12077
12078         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12079         {
12080                 vec4_t layercolor;
12081                 int layertexrgbscale;
12082                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12083                 {
12084                         if (layerindex == 0)
12085                                 GL_AlphaTest(true);
12086                         else
12087                         {
12088                                 GL_AlphaTest(false);
12089                                 GL_DepthFunc(GL_EQUAL);
12090                         }
12091                 }
12092                 GL_DepthMask(layer->depthmask && writedepth);
12093                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12094                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12095                 {
12096                         layertexrgbscale = 4;
12097                         VectorScale(layer->color, 0.25f, layercolor);
12098                 }
12099                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12100                 {
12101                         layertexrgbscale = 2;
12102                         VectorScale(layer->color, 0.5f, layercolor);
12103                 }
12104                 else
12105                 {
12106                         layertexrgbscale = 1;
12107                         VectorScale(layer->color, 1.0f, layercolor);
12108                 }
12109                 layercolor[3] = layer->color[3];
12110                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12111                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12112                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12113                 switch (layer->type)
12114                 {
12115                 case TEXTURELAYERTYPE_LITTEXTURE:
12116                         // single-pass lightmapped texture with 2x rgbscale
12117                         R_Mesh_TexBind(0, r_texture_white);
12118                         R_Mesh_TexMatrix(0, NULL);
12119                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12120                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12121                         R_Mesh_TexBind(1, layer->texture);
12122                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12123                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12124                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12125                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12126                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12127                         else if (FAKELIGHT_ENABLED)
12128                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12129                         else if (rsurface.uselightmaptexture)
12130                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12131                         else
12132                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12133                         break;
12134                 case TEXTURELAYERTYPE_TEXTURE:
12135                         // singletexture unlit texture with transparency support
12136                         R_Mesh_TexBind(0, layer->texture);
12137                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12138                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12139                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12140                         R_Mesh_TexBind(1, 0);
12141                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12142                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12143                         break;
12144                 case TEXTURELAYERTYPE_FOG:
12145                         // singletexture fogging
12146                         if (layer->texture)
12147                         {
12148                                 R_Mesh_TexBind(0, layer->texture);
12149                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12150                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12151                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12152                         }
12153                         else
12154                         {
12155                                 R_Mesh_TexBind(0, 0);
12156                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12157                         }
12158                         R_Mesh_TexBind(1, 0);
12159                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12160                         // generate a color array for the fog pass
12161                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12162                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12163                         RSurf_DrawBatch();
12164                         break;
12165                 default:
12166                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12167                 }
12168         }
12169         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12170         {
12171                 GL_DepthFunc(GL_LEQUAL);
12172                 GL_AlphaTest(false);
12173         }
12174 }
12175
12176 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12177 {
12178         // OpenGL 1.1 - crusty old voodoo path
12179         qboolean applyfog;
12180         int layerindex;
12181         const texturelayer_t *layer;
12182         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);
12183         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12184
12185         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12186         {
12187                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12188                 {
12189                         if (layerindex == 0)
12190                                 GL_AlphaTest(true);
12191                         else
12192                         {
12193                                 GL_AlphaTest(false);
12194                                 GL_DepthFunc(GL_EQUAL);
12195                         }
12196                 }
12197                 GL_DepthMask(layer->depthmask && writedepth);
12198                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12199                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12200                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12201                 switch (layer->type)
12202                 {
12203                 case TEXTURELAYERTYPE_LITTEXTURE:
12204                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12205                         {
12206                                 // two-pass lit texture with 2x rgbscale
12207                                 // first the lightmap pass
12208                                 R_Mesh_TexBind(0, r_texture_white);
12209                                 R_Mesh_TexMatrix(0, NULL);
12210                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12211                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12212                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12213                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12214                                 else if (FAKELIGHT_ENABLED)
12215                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12216                                 else if (rsurface.uselightmaptexture)
12217                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12218                                 else
12219                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12220                                 // then apply the texture to it
12221                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12222                                 R_Mesh_TexBind(0, layer->texture);
12223                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12224                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12225                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12226                                 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);
12227                         }
12228                         else
12229                         {
12230                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12231                                 R_Mesh_TexBind(0, layer->texture);
12232                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12233                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12234                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12235                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12236                                         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);
12237                                 else
12238                                         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);
12239                         }
12240                         break;
12241                 case TEXTURELAYERTYPE_TEXTURE:
12242                         // singletexture unlit texture with transparency support
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], 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);
12248                         break;
12249                 case TEXTURELAYERTYPE_FOG:
12250                         // singletexture fogging
12251                         if (layer->texture)
12252                         {
12253                                 R_Mesh_TexBind(0, layer->texture);
12254                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12255                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12256                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12257                         }
12258                         else
12259                         {
12260                                 R_Mesh_TexBind(0, 0);
12261                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12262                         }
12263                         // generate a color array for the fog pass
12264                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12265                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12266                         RSurf_DrawBatch();
12267                         break;
12268                 default:
12269                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12270                 }
12271         }
12272         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12273         {
12274                 GL_DepthFunc(GL_LEQUAL);
12275                 GL_AlphaTest(false);
12276         }
12277 }
12278
12279 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12280 {
12281         int vi;
12282         int j;
12283         r_vertexgeneric_t *batchvertex;
12284         float c[4];
12285
12286 //      R_Mesh_ResetTextureState();
12287         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12288
12289         if(rsurface.texture && rsurface.texture->currentskinframe)
12290         {
12291                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12292                 c[3] *= rsurface.texture->currentalpha;
12293         }
12294         else
12295         {
12296                 c[0] = 1;
12297                 c[1] = 0;
12298                 c[2] = 1;
12299                 c[3] = 1;
12300         }
12301
12302         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12303         {
12304                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12305                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12306                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12307         }
12308
12309         // brighten it up (as texture value 127 means "unlit")
12310         c[0] *= 2 * r_refdef.view.colorscale;
12311         c[1] *= 2 * r_refdef.view.colorscale;
12312         c[2] *= 2 * r_refdef.view.colorscale;
12313
12314         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12315                 c[3] *= r_wateralpha.value;
12316
12317         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12318         {
12319                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12320                 GL_DepthMask(false);
12321         }
12322         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12323         {
12324                 GL_BlendFunc(GL_ONE, GL_ONE);
12325                 GL_DepthMask(false);
12326         }
12327         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12328         {
12329                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12330                 GL_DepthMask(false);
12331         }
12332         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12333         {
12334                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12335                 GL_DepthMask(false);
12336         }
12337         else
12338         {
12339                 GL_BlendFunc(GL_ONE, GL_ZERO);
12340                 GL_DepthMask(writedepth);
12341         }
12342
12343         if (r_showsurfaces.integer == 3)
12344         {
12345                 rsurface.passcolor4f = NULL;
12346
12347                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12348                 {
12349                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12350
12351                         rsurface.passcolor4f = NULL;
12352                         rsurface.passcolor4f_vertexbuffer = 0;
12353                         rsurface.passcolor4f_bufferoffset = 0;
12354                 }
12355                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12356                 {
12357                         qboolean applycolor = true;
12358                         float one = 1.0;
12359
12360                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12361
12362                         r_refdef.lightmapintensity = 1;
12363                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12364                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12365                 }
12366                 else if (FAKELIGHT_ENABLED)
12367                 {
12368                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12369
12370                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12371                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12372                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12373                 }
12374                 else
12375                 {
12376                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12377
12378                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12379                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12380                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12381                 }
12382
12383                 if(!rsurface.passcolor4f)
12384                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12385
12386                 RSurf_DrawBatch_GL11_ApplyAmbient();
12387                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12388                 if(r_refdef.fogenabled)
12389                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12390                 RSurf_DrawBatch_GL11_ClampColor();
12391
12392                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12393                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12394                 RSurf_DrawBatch();
12395         }
12396         else if (!r_refdef.view.showdebug)
12397         {
12398                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12399                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12400                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12401                 {
12402                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12403                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12404                 }
12405                 R_Mesh_PrepareVertices_Generic_Unlock();
12406                 RSurf_DrawBatch();
12407         }
12408         else if (r_showsurfaces.integer == 4)
12409         {
12410                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12411                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12412                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12413                 {
12414                         unsigned char c = vi << 3;
12415                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12416                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12417                 }
12418                 R_Mesh_PrepareVertices_Generic_Unlock();
12419                 RSurf_DrawBatch();
12420         }
12421         else if (r_showsurfaces.integer == 2)
12422         {
12423                 const int *e;
12424                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12425                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12426                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12427                 {
12428                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12429                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12430                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12431                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12432                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12433                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12434                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12435                 }
12436                 R_Mesh_PrepareVertices_Generic_Unlock();
12437                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12438         }
12439         else
12440         {
12441                 int texturesurfaceindex;
12442                 int k;
12443                 const msurface_t *surface;
12444                 unsigned char surfacecolor4ub[4];
12445                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12446                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12447                 vi = 0;
12448                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12449                 {
12450                         surface = texturesurfacelist[texturesurfaceindex];
12451                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12452                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12453                         for (j = 0;j < surface->num_vertices;j++)
12454                         {
12455                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12456                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12457                                 vi++;
12458                         }
12459                 }
12460                 R_Mesh_PrepareVertices_Generic_Unlock();
12461                 RSurf_DrawBatch();
12462         }
12463 }
12464
12465 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12466 {
12467         CHECKGLERROR
12468         RSurf_SetupDepthAndCulling();
12469         if (r_showsurfaces.integer)
12470         {
12471                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12472                 return;
12473         }
12474         switch (vid.renderpath)
12475         {
12476         case RENDERPATH_GL20:
12477         case RENDERPATH_D3D9:
12478         case RENDERPATH_D3D10:
12479         case RENDERPATH_D3D11:
12480         case RENDERPATH_SOFT:
12481         case RENDERPATH_GLES2:
12482                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12483                 break;
12484         case RENDERPATH_GL13:
12485                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12486                 break;
12487         case RENDERPATH_GL11:
12488                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12489                 break;
12490         }
12491         CHECKGLERROR
12492 }
12493
12494 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12495 {
12496         CHECKGLERROR
12497         RSurf_SetupDepthAndCulling();
12498         if (r_showsurfaces.integer)
12499         {
12500                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12501                 return;
12502         }
12503         switch (vid.renderpath)
12504         {
12505         case RENDERPATH_GL20:
12506         case RENDERPATH_D3D9:
12507         case RENDERPATH_D3D10:
12508         case RENDERPATH_D3D11:
12509         case RENDERPATH_SOFT:
12510         case RENDERPATH_GLES2:
12511                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12512                 break;
12513         case RENDERPATH_GL13:
12514                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12515                 break;
12516         case RENDERPATH_GL11:
12517                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12518                 break;
12519         }
12520         CHECKGLERROR
12521 }
12522
12523 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12524 {
12525         int i, j;
12526         int texturenumsurfaces, endsurface;
12527         texture_t *texture;
12528         const msurface_t *surface;
12529 #define MAXBATCH_TRANSPARENTSURFACES 256
12530         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12531
12532         // if the model is static it doesn't matter what value we give for
12533         // wantnormals and wanttangents, so this logic uses only rules applicable
12534         // to a model, knowing that they are meaningless otherwise
12535         if (ent == r_refdef.scene.worldentity)
12536                 RSurf_ActiveWorldEntity();
12537         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12538                 RSurf_ActiveModelEntity(ent, false, false, false);
12539         else
12540         {
12541                 switch (vid.renderpath)
12542                 {
12543                 case RENDERPATH_GL20:
12544                 case RENDERPATH_D3D9:
12545                 case RENDERPATH_D3D10:
12546                 case RENDERPATH_D3D11:
12547                 case RENDERPATH_SOFT:
12548                 case RENDERPATH_GLES2:
12549                         RSurf_ActiveModelEntity(ent, true, true, false);
12550                         break;
12551                 case RENDERPATH_GL13:
12552                 case RENDERPATH_GL11:
12553                         RSurf_ActiveModelEntity(ent, true, false, false);
12554                         break;
12555                 }
12556         }
12557
12558         if (r_transparentdepthmasking.integer)
12559         {
12560                 qboolean setup = false;
12561                 for (i = 0;i < numsurfaces;i = j)
12562                 {
12563                         j = i + 1;
12564                         surface = rsurface.modelsurfaces + surfacelist[i];
12565                         texture = surface->texture;
12566                         rsurface.texture = R_GetCurrentTexture(texture);
12567                         rsurface.lightmaptexture = NULL;
12568                         rsurface.deluxemaptexture = NULL;
12569                         rsurface.uselightmaptexture = false;
12570                         // scan ahead until we find a different texture
12571                         endsurface = min(i + 1024, numsurfaces);
12572                         texturenumsurfaces = 0;
12573                         texturesurfacelist[texturenumsurfaces++] = surface;
12574                         for (;j < endsurface;j++)
12575                         {
12576                                 surface = rsurface.modelsurfaces + surfacelist[j];
12577                                 if (texture != surface->texture)
12578                                         break;
12579                                 texturesurfacelist[texturenumsurfaces++] = surface;
12580                         }
12581                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12582                                 continue;
12583                         // render the range of surfaces as depth
12584                         if (!setup)
12585                         {
12586                                 setup = true;
12587                                 GL_ColorMask(0,0,0,0);
12588                                 GL_Color(1,1,1,1);
12589                                 GL_DepthTest(true);
12590                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12591                                 GL_DepthMask(true);
12592 //                              R_Mesh_ResetTextureState();
12593                                 R_SetupShader_DepthOrShadow();
12594                         }
12595                         RSurf_SetupDepthAndCulling();
12596                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12597                         if (rsurface.batchvertex3fbuffer)
12598                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12599                         else
12600                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12601                         RSurf_DrawBatch();
12602                 }
12603                 if (setup)
12604                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12605         }
12606
12607         for (i = 0;i < numsurfaces;i = j)
12608         {
12609                 j = i + 1;
12610                 surface = rsurface.modelsurfaces + surfacelist[i];
12611                 texture = surface->texture;
12612                 rsurface.texture = R_GetCurrentTexture(texture);
12613                 // scan ahead until we find a different texture
12614                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12615                 texturenumsurfaces = 0;
12616                 texturesurfacelist[texturenumsurfaces++] = surface;
12617                 if(FAKELIGHT_ENABLED)
12618                 {
12619                         rsurface.lightmaptexture = NULL;
12620                         rsurface.deluxemaptexture = NULL;
12621                         rsurface.uselightmaptexture = false;
12622                         for (;j < endsurface;j++)
12623                         {
12624                                 surface = rsurface.modelsurfaces + surfacelist[j];
12625                                 if (texture != surface->texture)
12626                                         break;
12627                                 texturesurfacelist[texturenumsurfaces++] = surface;
12628                         }
12629                 }
12630                 else
12631                 {
12632                         rsurface.lightmaptexture = surface->lightmaptexture;
12633                         rsurface.deluxemaptexture = surface->deluxemaptexture;
12634                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12635                         for (;j < endsurface;j++)
12636                         {
12637                                 surface = rsurface.modelsurfaces + surfacelist[j];
12638                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12639                                         break;
12640                                 texturesurfacelist[texturenumsurfaces++] = surface;
12641                         }
12642                 }
12643                 // render the range of surfaces
12644                 if (ent == r_refdef.scene.worldentity)
12645                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12646                 else
12647                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12648         }
12649         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12650 }
12651
12652 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12653 {
12654         // transparent surfaces get pushed off into the transparent queue
12655         int surfacelistindex;
12656         const msurface_t *surface;
12657         vec3_t tempcenter, center;
12658         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12659         {
12660                 surface = texturesurfacelist[surfacelistindex];
12661                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12662                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12663                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12664                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12665                 if (queueentity->transparent_offset) // transparent offset
12666                 {
12667                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12668                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12669                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12670                 }
12671                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12672         }
12673 }
12674
12675 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12676 {
12677         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12678                 return;
12679         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12680                 return;
12681         RSurf_SetupDepthAndCulling();
12682         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12683         if (rsurface.batchvertex3fbuffer)
12684                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12685         else
12686                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12687         RSurf_DrawBatch();
12688 }
12689
12690 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12691 {
12692         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12693         CHECKGLERROR
12694         if (depthonly)
12695                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12696         else if (prepass)
12697         {
12698                 if (!rsurface.texture->currentnumlayers)
12699                         return;
12700                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12701                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12702                 else
12703                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12704         }
12705         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12706                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12707         else if (!rsurface.texture->currentnumlayers)
12708                 return;
12709         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12710         {
12711                 // in the deferred case, transparent surfaces were queued during prepass
12712                 if (!r_shadow_usingdeferredprepass)
12713                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12714         }
12715         else
12716         {
12717                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12718                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12719         }
12720         CHECKGLERROR
12721 }
12722
12723 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12724 {
12725         int i, j;
12726         texture_t *texture;
12727         R_FrameData_SetMark();
12728         // break the surface list down into batches by texture and use of lightmapping
12729         for (i = 0;i < numsurfaces;i = j)
12730         {
12731                 j = i + 1;
12732                 // texture is the base texture pointer, rsurface.texture is the
12733                 // current frame/skin the texture is directing us to use (for example
12734                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12735                 // use skin 1 instead)
12736                 texture = surfacelist[i]->texture;
12737                 rsurface.texture = R_GetCurrentTexture(texture);
12738                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12739                 {
12740                         // if this texture is not the kind we want, skip ahead to the next one
12741                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12742                                 ;
12743                         continue;
12744                 }
12745                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12746                 {
12747                         rsurface.lightmaptexture = NULL;
12748                         rsurface.deluxemaptexture = NULL;
12749                         rsurface.uselightmaptexture = false;
12750                         // simply scan ahead until we find a different texture or lightmap state
12751                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12752                                 ;
12753                 }
12754                 else
12755                 {
12756                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12757                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12758                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12759                         // simply scan ahead until we find a different texture or lightmap state
12760                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12761                                 ;
12762                 }
12763                 // render the range of surfaces
12764                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12765         }
12766         R_FrameData_ReturnToMark();
12767 }
12768
12769 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12770 {
12771         CHECKGLERROR
12772         if (depthonly)
12773                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12774         else if (prepass)
12775         {
12776                 if (!rsurface.texture->currentnumlayers)
12777                         return;
12778                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12779                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12780                 else
12781                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12782         }
12783         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12784                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12785         else if (!rsurface.texture->currentnumlayers)
12786                 return;
12787         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12788         {
12789                 // in the deferred case, transparent surfaces were queued during prepass
12790                 if (!r_shadow_usingdeferredprepass)
12791                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12792         }
12793         else
12794         {
12795                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12796                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12797         }
12798         CHECKGLERROR
12799 }
12800
12801 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12802 {
12803         int i, j;
12804         texture_t *texture;
12805         R_FrameData_SetMark();
12806         // break the surface list down into batches by texture and use of lightmapping
12807         for (i = 0;i < numsurfaces;i = j)
12808         {
12809                 j = i + 1;
12810                 // texture is the base texture pointer, rsurface.texture is the
12811                 // current frame/skin the texture is directing us to use (for example
12812                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12813                 // use skin 1 instead)
12814                 texture = surfacelist[i]->texture;
12815                 rsurface.texture = R_GetCurrentTexture(texture);
12816                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12817                 {
12818                         // if this texture is not the kind we want, skip ahead to the next one
12819                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12820                                 ;
12821                         continue;
12822                 }
12823                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12824                 {
12825                         rsurface.lightmaptexture = NULL;
12826                         rsurface.deluxemaptexture = NULL;
12827                         rsurface.uselightmaptexture = false;
12828                         // simply scan ahead until we find a different texture or lightmap state
12829                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12830                                 ;
12831                 }
12832                 else
12833                 {
12834                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12835                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12836                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12837                         // simply scan ahead until we find a different texture or lightmap state
12838                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12839                                 ;
12840                 }
12841                 // render the range of surfaces
12842                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12843         }
12844         R_FrameData_ReturnToMark();
12845 }
12846
12847 float locboxvertex3f[6*4*3] =
12848 {
12849         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12850         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12851         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12852         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12853         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12854         1,0,0, 0,0,0, 0,1,0, 1,1,0
12855 };
12856
12857 unsigned short locboxelements[6*2*3] =
12858 {
12859          0, 1, 2, 0, 2, 3,
12860          4, 5, 6, 4, 6, 7,
12861          8, 9,10, 8,10,11,
12862         12,13,14, 12,14,15,
12863         16,17,18, 16,18,19,
12864         20,21,22, 20,22,23
12865 };
12866
12867 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12868 {
12869         int i, j;
12870         cl_locnode_t *loc = (cl_locnode_t *)ent;
12871         vec3_t mins, size;
12872         float vertex3f[6*4*3];
12873         CHECKGLERROR
12874         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12875         GL_DepthMask(false);
12876         GL_DepthRange(0, 1);
12877         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12878         GL_DepthTest(true);
12879         GL_CullFace(GL_NONE);
12880         R_EntityMatrix(&identitymatrix);
12881
12882 //      R_Mesh_ResetTextureState();
12883
12884         i = surfacelist[0];
12885         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12886                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12887                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12888                         surfacelist[0] < 0 ? 0.5f : 0.125f);
12889
12890         if (VectorCompare(loc->mins, loc->maxs))
12891         {
12892                 VectorSet(size, 2, 2, 2);
12893                 VectorMA(loc->mins, -0.5f, size, mins);
12894         }
12895         else
12896         {
12897                 VectorCopy(loc->mins, mins);
12898                 VectorSubtract(loc->maxs, loc->mins, size);
12899         }
12900
12901         for (i = 0;i < 6*4*3;)
12902                 for (j = 0;j < 3;j++, i++)
12903                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12904
12905         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12906         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12907         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12908 }
12909
12910 void R_DrawLocs(void)
12911 {
12912         int index;
12913         cl_locnode_t *loc, *nearestloc;
12914         vec3_t center;
12915         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12916         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12917         {
12918                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12919                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12920         }
12921 }
12922
12923 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12924 {
12925         if (decalsystem->decals)
12926                 Mem_Free(decalsystem->decals);
12927         memset(decalsystem, 0, sizeof(*decalsystem));
12928 }
12929
12930 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)
12931 {
12932         tridecal_t *decal;
12933         tridecal_t *decals;
12934         int i;
12935
12936         // expand or initialize the system
12937         if (decalsystem->maxdecals <= decalsystem->numdecals)
12938         {
12939                 decalsystem_t old = *decalsystem;
12940                 qboolean useshortelements;
12941                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12942                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12943                 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)));
12944                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12945                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12946                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12947                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12948                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12949                 if (decalsystem->numdecals)
12950                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12951                 if (old.decals)
12952                         Mem_Free(old.decals);
12953                 for (i = 0;i < decalsystem->maxdecals*3;i++)
12954                         decalsystem->element3i[i] = i;
12955                 if (useshortelements)
12956                         for (i = 0;i < decalsystem->maxdecals*3;i++)
12957                                 decalsystem->element3s[i] = i;
12958         }
12959
12960         // grab a decal and search for another free slot for the next one
12961         decals = decalsystem->decals;
12962         decal = decalsystem->decals + (i = decalsystem->freedecal++);
12963         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
12964                 ;
12965         decalsystem->freedecal = i;
12966         if (decalsystem->numdecals <= i)
12967                 decalsystem->numdecals = i + 1;
12968
12969         // initialize the decal
12970         decal->lived = 0;
12971         decal->triangleindex = triangleindex;
12972         decal->surfaceindex = surfaceindex;
12973         decal->decalsequence = decalsequence;
12974         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
12975         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
12976         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
12977         decal->color4ub[0][3] = 255;
12978         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
12979         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
12980         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
12981         decal->color4ub[1][3] = 255;
12982         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
12983         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
12984         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
12985         decal->color4ub[2][3] = 255;
12986         decal->vertex3f[0][0] = v0[0];
12987         decal->vertex3f[0][1] = v0[1];
12988         decal->vertex3f[0][2] = v0[2];
12989         decal->vertex3f[1][0] = v1[0];
12990         decal->vertex3f[1][1] = v1[1];
12991         decal->vertex3f[1][2] = v1[2];
12992         decal->vertex3f[2][0] = v2[0];
12993         decal->vertex3f[2][1] = v2[1];
12994         decal->vertex3f[2][2] = v2[2];
12995         decal->texcoord2f[0][0] = t0[0];
12996         decal->texcoord2f[0][1] = t0[1];
12997         decal->texcoord2f[1][0] = t1[0];
12998         decal->texcoord2f[1][1] = t1[1];
12999         decal->texcoord2f[2][0] = t2[0];
13000         decal->texcoord2f[2][1] = t2[1];
13001 }
13002
13003 extern cvar_t cl_decals_bias;
13004 extern cvar_t cl_decals_models;
13005 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13006 // baseparms, parms, temps
13007 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)
13008 {
13009         int cornerindex;
13010         int index;
13011         float v[9][3];
13012         const float *vertex3f;
13013         int numpoints;
13014         float points[2][9][3];
13015         float temp[3];
13016         float tc[9][2];
13017         float f;
13018         float c[9][4];
13019         const int *e;
13020
13021         e = rsurface.modelelement3i + 3*triangleindex;
13022
13023         vertex3f = rsurface.modelvertex3f;
13024
13025         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13026         {
13027                 index = 3*e[cornerindex];
13028                 VectorCopy(vertex3f + index, v[cornerindex]);
13029         }
13030         // cull backfaces
13031         //TriangleNormal(v[0], v[1], v[2], normal);
13032         //if (DotProduct(normal, localnormal) < 0.0f)
13033         //      continue;
13034         // clip by each of the box planes formed from the projection matrix
13035         // if anything survives, we emit the decal
13036         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]);
13037         if (numpoints < 3)
13038                 return;
13039         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]);
13040         if (numpoints < 3)
13041                 return;
13042         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]);
13043         if (numpoints < 3)
13044                 return;
13045         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]);
13046         if (numpoints < 3)
13047                 return;
13048         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]);
13049         if (numpoints < 3)
13050                 return;
13051         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]);
13052         if (numpoints < 3)
13053                 return;
13054         // some part of the triangle survived, so we have to accept it...
13055         if (dynamic)
13056         {
13057                 // dynamic always uses the original triangle
13058                 numpoints = 3;
13059                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13060                 {
13061                         index = 3*e[cornerindex];
13062                         VectorCopy(vertex3f + index, v[cornerindex]);
13063                 }
13064         }
13065         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13066         {
13067                 // convert vertex positions to texcoords
13068                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13069                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13070                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13071                 // calculate distance fade from the projection origin
13072                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13073                 f = bound(0.0f, f, 1.0f);
13074                 c[cornerindex][0] = r * f;
13075                 c[cornerindex][1] = g * f;
13076                 c[cornerindex][2] = b * f;
13077                 c[cornerindex][3] = 1.0f;
13078                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13079         }
13080         if (dynamic)
13081                 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);
13082         else
13083                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13084                         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);
13085 }
13086 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)
13087 {
13088         matrix4x4_t projection;
13089         decalsystem_t *decalsystem;
13090         qboolean dynamic;
13091         dp_model_t *model;
13092         const msurface_t *surface;
13093         const msurface_t *surfaces;
13094         const int *surfacelist;
13095         const texture_t *texture;
13096         int numtriangles;
13097         int numsurfacelist;
13098         int surfacelistindex;
13099         int surfaceindex;
13100         int triangleindex;
13101         float localorigin[3];
13102         float localnormal[3];
13103         float localmins[3];
13104         float localmaxs[3];
13105         float localsize;
13106         //float normal[3];
13107         float planes[6][4];
13108         float angles[3];
13109         bih_t *bih;
13110         int bih_triangles_count;
13111         int bih_triangles[256];
13112         int bih_surfaces[256];
13113
13114         decalsystem = &ent->decalsystem;
13115         model = ent->model;
13116         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13117         {
13118                 R_DecalSystem_Reset(&ent->decalsystem);
13119                 return;
13120         }
13121
13122         if (!model->brush.data_leafs && !cl_decals_models.integer)
13123         {
13124                 if (decalsystem->model)
13125                         R_DecalSystem_Reset(decalsystem);
13126                 return;
13127         }
13128
13129         if (decalsystem->model != model)
13130                 R_DecalSystem_Reset(decalsystem);
13131         decalsystem->model = model;
13132
13133         RSurf_ActiveModelEntity(ent, false, false, false);
13134
13135         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13136         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13137         VectorNormalize(localnormal);
13138         localsize = worldsize*rsurface.inversematrixscale;
13139         localmins[0] = localorigin[0] - localsize;
13140         localmins[1] = localorigin[1] - localsize;
13141         localmins[2] = localorigin[2] - localsize;
13142         localmaxs[0] = localorigin[0] + localsize;
13143         localmaxs[1] = localorigin[1] + localsize;
13144         localmaxs[2] = localorigin[2] + localsize;
13145
13146         //VectorCopy(localnormal, planes[4]);
13147         //VectorVectors(planes[4], planes[2], planes[0]);
13148         AnglesFromVectors(angles, localnormal, NULL, false);
13149         AngleVectors(angles, planes[0], planes[2], planes[4]);
13150         VectorNegate(planes[0], planes[1]);
13151         VectorNegate(planes[2], planes[3]);
13152         VectorNegate(planes[4], planes[5]);
13153         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13154         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13155         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13156         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13157         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13158         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13159
13160 #if 1
13161 // works
13162 {
13163         matrix4x4_t forwardprojection;
13164         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13165         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13166 }
13167 #else
13168 // broken
13169 {
13170         float projectionvector[4][3];
13171         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13172         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13173         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13174         projectionvector[0][0] = planes[0][0] * ilocalsize;
13175         projectionvector[0][1] = planes[1][0] * ilocalsize;
13176         projectionvector[0][2] = planes[2][0] * ilocalsize;
13177         projectionvector[1][0] = planes[0][1] * ilocalsize;
13178         projectionvector[1][1] = planes[1][1] * ilocalsize;
13179         projectionvector[1][2] = planes[2][1] * ilocalsize;
13180         projectionvector[2][0] = planes[0][2] * ilocalsize;
13181         projectionvector[2][1] = planes[1][2] * ilocalsize;
13182         projectionvector[2][2] = planes[2][2] * ilocalsize;
13183         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13184         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13185         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13186         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13187 }
13188 #endif
13189
13190         dynamic = model->surfmesh.isanimated;
13191         numsurfacelist = model->nummodelsurfaces;
13192         surfacelist = model->sortedmodelsurfaces;
13193         surfaces = model->data_surfaces;
13194
13195         bih = NULL;
13196         bih_triangles_count = -1;
13197         if(!dynamic)
13198         {
13199                 if(model->render_bih.numleafs)
13200                         bih = &model->render_bih;
13201                 else if(model->collision_bih.numleafs)
13202                         bih = &model->collision_bih;
13203         }
13204         if(bih)
13205                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13206         if(bih_triangles_count == 0)
13207                 return;
13208         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13209                 return;
13210         if(bih_triangles_count > 0)
13211         {
13212                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13213                 {
13214                         surfaceindex = bih_surfaces[triangleindex];
13215                         surface = surfaces + surfaceindex;
13216                         texture = surface->texture;
13217                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13218                                 continue;
13219                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13220                                 continue;
13221                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13222                 }
13223         }
13224         else
13225         {
13226                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13227                 {
13228                         surfaceindex = surfacelist[surfacelistindex];
13229                         surface = surfaces + surfaceindex;
13230                         // check cull box first because it rejects more than any other check
13231                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13232                                 continue;
13233                         // skip transparent surfaces
13234                         texture = surface->texture;
13235                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13236                                 continue;
13237                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13238                                 continue;
13239                         numtriangles = surface->num_triangles;
13240                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13241                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13242                 }
13243         }
13244 }
13245
13246 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13247 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)
13248 {
13249         int renderentityindex;
13250         float worldmins[3];
13251         float worldmaxs[3];
13252         entity_render_t *ent;
13253
13254         if (!cl_decals_newsystem.integer)
13255                 return;
13256
13257         worldmins[0] = worldorigin[0] - worldsize;
13258         worldmins[1] = worldorigin[1] - worldsize;
13259         worldmins[2] = worldorigin[2] - worldsize;
13260         worldmaxs[0] = worldorigin[0] + worldsize;
13261         worldmaxs[1] = worldorigin[1] + worldsize;
13262         worldmaxs[2] = worldorigin[2] + worldsize;
13263
13264         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13265
13266         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13267         {
13268                 ent = r_refdef.scene.entities[renderentityindex];
13269                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13270                         continue;
13271
13272                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13273         }
13274 }
13275
13276 typedef struct r_decalsystem_splatqueue_s
13277 {
13278         vec3_t worldorigin;
13279         vec3_t worldnormal;
13280         float color[4];
13281         float tcrange[4];
13282         float worldsize;
13283         int decalsequence;
13284 }
13285 r_decalsystem_splatqueue_t;
13286
13287 int r_decalsystem_numqueued = 0;
13288 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13289
13290 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)
13291 {
13292         r_decalsystem_splatqueue_t *queue;
13293
13294         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13295                 return;
13296
13297         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13298         VectorCopy(worldorigin, queue->worldorigin);
13299         VectorCopy(worldnormal, queue->worldnormal);
13300         Vector4Set(queue->color, r, g, b, a);
13301         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13302         queue->worldsize = worldsize;
13303         queue->decalsequence = cl.decalsequence++;
13304 }
13305
13306 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13307 {
13308         int i;
13309         r_decalsystem_splatqueue_t *queue;
13310
13311         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13312                 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);
13313         r_decalsystem_numqueued = 0;
13314 }
13315
13316 extern cvar_t cl_decals_max;
13317 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13318 {
13319         int i;
13320         decalsystem_t *decalsystem = &ent->decalsystem;
13321         int numdecals;
13322         int killsequence;
13323         tridecal_t *decal;
13324         float frametime;
13325         float lifetime;
13326
13327         if (!decalsystem->numdecals)
13328                 return;
13329
13330         if (r_showsurfaces.integer)
13331                 return;
13332
13333         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13334         {
13335                 R_DecalSystem_Reset(decalsystem);
13336                 return;
13337         }
13338
13339         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13340         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13341
13342         if (decalsystem->lastupdatetime)
13343                 frametime = (cl.time - decalsystem->lastupdatetime);
13344         else
13345                 frametime = 0;
13346         decalsystem->lastupdatetime = cl.time;
13347         decal = decalsystem->decals;
13348         numdecals = decalsystem->numdecals;
13349
13350         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13351         {
13352                 if (decal->color4ub[0][3])
13353                 {
13354                         decal->lived += frametime;
13355                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13356                         {
13357                                 memset(decal, 0, sizeof(*decal));
13358                                 if (decalsystem->freedecal > i)
13359                                         decalsystem->freedecal = i;
13360                         }
13361                 }
13362         }
13363         decal = decalsystem->decals;
13364         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13365                 numdecals--;
13366
13367         // collapse the array by shuffling the tail decals into the gaps
13368         for (;;)
13369         {
13370                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13371                         decalsystem->freedecal++;
13372                 if (decalsystem->freedecal == numdecals)
13373                         break;
13374                 decal[decalsystem->freedecal] = decal[--numdecals];
13375         }
13376
13377         decalsystem->numdecals = numdecals;
13378
13379         if (numdecals <= 0)
13380         {
13381                 // if there are no decals left, reset decalsystem
13382                 R_DecalSystem_Reset(decalsystem);
13383         }
13384 }
13385
13386 extern skinframe_t *decalskinframe;
13387 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13388 {
13389         int i;
13390         decalsystem_t *decalsystem = &ent->decalsystem;
13391         int numdecals;
13392         tridecal_t *decal;
13393         float faderate;
13394         float alpha;
13395         float *v3f;
13396         float *c4f;
13397         float *t2f;
13398         const int *e;
13399         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13400         int numtris = 0;
13401
13402         numdecals = decalsystem->numdecals;
13403         if (!numdecals)
13404                 return;
13405
13406         if (r_showsurfaces.integer)
13407                 return;
13408
13409         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13410         {
13411                 R_DecalSystem_Reset(decalsystem);
13412                 return;
13413         }
13414
13415         // if the model is static it doesn't matter what value we give for
13416         // wantnormals and wanttangents, so this logic uses only rules applicable
13417         // to a model, knowing that they are meaningless otherwise
13418         if (ent == r_refdef.scene.worldentity)
13419                 RSurf_ActiveWorldEntity();
13420         else
13421                 RSurf_ActiveModelEntity(ent, false, false, false);
13422
13423         decalsystem->lastupdatetime = cl.time;
13424         decal = decalsystem->decals;
13425
13426         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13427
13428         // update vertex positions for animated models
13429         v3f = decalsystem->vertex3f;
13430         c4f = decalsystem->color4f;
13431         t2f = decalsystem->texcoord2f;
13432         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13433         {
13434                 if (!decal->color4ub[0][3])
13435                         continue;
13436
13437                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13438                         continue;
13439
13440                 // update color values for fading decals
13441                 if (decal->lived >= cl_decals_time.value)
13442                 {
13443                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13444                         alpha *= (1.0f/255.0f);
13445                 }
13446                 else
13447                         alpha = 1.0f/255.0f;
13448
13449                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13450                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13451                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13452                 c4f[ 3] = 1;
13453                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13454                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13455                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13456                 c4f[ 7] = 1;
13457                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13458                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13459                 c4f[10] = decal->color4ub[2][2] * alpha;
13460                 c4f[11] = 1;
13461
13462                 t2f[0] = decal->texcoord2f[0][0];
13463                 t2f[1] = decal->texcoord2f[0][1];
13464                 t2f[2] = decal->texcoord2f[1][0];
13465                 t2f[3] = decal->texcoord2f[1][1];
13466                 t2f[4] = decal->texcoord2f[2][0];
13467                 t2f[5] = decal->texcoord2f[2][1];
13468
13469                 // update vertex positions for animated models
13470                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13471                 {
13472                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13473                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
13474                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
13475                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
13476                 }
13477                 else
13478                 {
13479                         VectorCopy(decal->vertex3f[0], v3f);
13480                         VectorCopy(decal->vertex3f[1], v3f + 3);
13481                         VectorCopy(decal->vertex3f[2], v3f + 6);
13482                 }
13483
13484                 if (r_refdef.fogenabled)
13485                 {
13486                         alpha = RSurf_FogVertex(v3f);
13487                         VectorScale(c4f, alpha, c4f);
13488                         alpha = RSurf_FogVertex(v3f + 3);
13489                         VectorScale(c4f + 4, alpha, c4f + 4);
13490                         alpha = RSurf_FogVertex(v3f + 6);
13491                         VectorScale(c4f + 8, alpha, c4f + 8);
13492                 }
13493
13494                 v3f += 9;
13495                 c4f += 12;
13496                 t2f += 6;
13497                 numtris++;
13498         }
13499
13500         if (numtris > 0)
13501         {
13502                 r_refdef.stats.drawndecals += numtris;
13503
13504                 // now render the decals all at once
13505                 // (this assumes they all use one particle font texture!)
13506                 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);
13507 //              R_Mesh_ResetTextureState();
13508                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13509                 GL_DepthMask(false);
13510                 GL_DepthRange(0, 1);
13511                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13512                 GL_DepthTest(true);
13513                 GL_CullFace(GL_NONE);
13514                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13515                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13516                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13517         }
13518 }
13519
13520 static void R_DrawModelDecals(void)
13521 {
13522         int i, numdecals;
13523
13524         // fade faster when there are too many decals
13525         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13526         for (i = 0;i < r_refdef.scene.numentities;i++)
13527                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13528
13529         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13530         for (i = 0;i < r_refdef.scene.numentities;i++)
13531                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13532                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13533
13534         R_DecalSystem_ApplySplatEntitiesQueue();
13535
13536         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13537         for (i = 0;i < r_refdef.scene.numentities;i++)
13538                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13539
13540         r_refdef.stats.totaldecals += numdecals;
13541
13542         if (r_showsurfaces.integer)
13543                 return;
13544
13545         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13546
13547         for (i = 0;i < r_refdef.scene.numentities;i++)
13548         {
13549                 if (!r_refdef.viewcache.entityvisible[i])
13550                         continue;
13551                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13552                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13553         }
13554 }
13555
13556 extern cvar_t mod_collision_bih;
13557 void R_DrawDebugModel(void)
13558 {
13559         entity_render_t *ent = rsurface.entity;
13560         int i, j, k, l, flagsmask;
13561         const msurface_t *surface;
13562         dp_model_t *model = ent->model;
13563         vec3_t v;
13564
13565         switch(vid.renderpath)
13566         {
13567         case RENDERPATH_GL11:
13568         case RENDERPATH_GL13:
13569         case RENDERPATH_GL20:
13570                 break;
13571         case RENDERPATH_D3D9:
13572                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13573                 return;
13574         case RENDERPATH_D3D10:
13575                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13576                 return;
13577         case RENDERPATH_D3D11:
13578                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13579                 return;
13580         case RENDERPATH_SOFT:
13581                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13582                 return;
13583         case RENDERPATH_GLES2:
13584                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13585                 return;
13586         }
13587
13588         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13589
13590 //      R_Mesh_ResetTextureState();
13591         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13592         GL_DepthRange(0, 1);
13593         GL_DepthTest(!r_showdisabledepthtest.integer);
13594         GL_DepthMask(false);
13595         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13596
13597         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13598         {
13599                 int triangleindex;
13600                 int bihleafindex;
13601                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13602                 const q3mbrush_t *brush;
13603                 const bih_t *bih = &model->collision_bih;
13604                 const bih_leaf_t *bihleaf;
13605                 float vertex3f[3][3];
13606                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13607                 cullbox = false;
13608                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13609                 {
13610                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13611                                 continue;
13612                         switch (bihleaf->type)
13613                         {
13614                         case BIH_BRUSH:
13615                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13616                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13617                                 {
13618                                         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);
13619                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13620                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13621                                 }
13622                                 break;
13623                         case BIH_COLLISIONTRIANGLE:
13624                                 triangleindex = bihleaf->itemindex;
13625                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13626                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13627                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13628                                 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);
13629                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13630                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13631                                 break;
13632                         case BIH_RENDERTRIANGLE:
13633                                 triangleindex = bihleaf->itemindex;
13634                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13635                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13636                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13637                                 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);
13638                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13639                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13640                                 break;
13641                         }
13642                 }
13643         }
13644
13645         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13646
13647         if (r_showtris.integer || (r_shownormals.value != 0))
13648         {
13649                 if (r_showdisabledepthtest.integer)
13650                 {
13651                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13652                         GL_DepthMask(false);
13653                 }
13654                 else
13655                 {
13656                         GL_BlendFunc(GL_ONE, GL_ZERO);
13657                         GL_DepthMask(true);
13658                 }
13659                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13660                 {
13661                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13662                                 continue;
13663                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13664                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13665                         {
13666                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13667                                 if (r_showtris.value > 0)
13668                                 {
13669                                         if (!rsurface.texture->currentlayers->depthmask)
13670                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13671                                         else if (ent == r_refdef.scene.worldentity)
13672                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13673                                         else
13674                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13675                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13676                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13677                                         RSurf_DrawBatch();
13678                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13679                                         CHECKGLERROR
13680                                 }
13681                                 if (r_shownormals.value < 0)
13682                                 {
13683                                         qglBegin(GL_LINES);
13684                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13685                                         {
13686                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13687                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13688                                                 qglVertex3f(v[0], v[1], v[2]);
13689                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13690                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13691                                                 qglVertex3f(v[0], v[1], v[2]);
13692                                         }
13693                                         qglEnd();
13694                                         CHECKGLERROR
13695                                 }
13696                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13697                                 {
13698                                         qglBegin(GL_LINES);
13699                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13700                                         {
13701                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13702                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13703                                                 qglVertex3f(v[0], v[1], v[2]);
13704                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13705                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13706                                                 qglVertex3f(v[0], v[1], v[2]);
13707                                         }
13708                                         qglEnd();
13709                                         CHECKGLERROR
13710                                         qglBegin(GL_LINES);
13711                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13712                                         {
13713                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13714                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13715                                                 qglVertex3f(v[0], v[1], v[2]);
13716                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13717                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13718                                                 qglVertex3f(v[0], v[1], v[2]);
13719                                         }
13720                                         qglEnd();
13721                                         CHECKGLERROR
13722                                         qglBegin(GL_LINES);
13723                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13724                                         {
13725                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13726                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13727                                                 qglVertex3f(v[0], v[1], v[2]);
13728                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13729                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13730                                                 qglVertex3f(v[0], v[1], v[2]);
13731                                         }
13732                                         qglEnd();
13733                                         CHECKGLERROR
13734                                 }
13735                         }
13736                 }
13737                 rsurface.texture = NULL;
13738         }
13739 }
13740
13741 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13742 int r_maxsurfacelist = 0;
13743 const msurface_t **r_surfacelist = NULL;
13744 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13745 {
13746         int i, j, endj, flagsmask;
13747         dp_model_t *model = r_refdef.scene.worldmodel;
13748         msurface_t *surfaces;
13749         unsigned char *update;
13750         int numsurfacelist = 0;
13751         if (model == NULL)
13752                 return;
13753
13754         if (r_maxsurfacelist < model->num_surfaces)
13755         {
13756                 r_maxsurfacelist = model->num_surfaces;
13757                 if (r_surfacelist)
13758                         Mem_Free((msurface_t**)r_surfacelist);
13759                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13760         }
13761
13762         RSurf_ActiveWorldEntity();
13763
13764         surfaces = model->data_surfaces;
13765         update = model->brushq1.lightmapupdateflags;
13766
13767         // update light styles on this submodel
13768         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13769         {
13770                 model_brush_lightstyleinfo_t *style;
13771                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13772                 {
13773                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13774                         {
13775                                 int *list = style->surfacelist;
13776                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13777                                 for (j = 0;j < style->numsurfaces;j++)
13778                                         update[list[j]] = true;
13779                         }
13780                 }
13781         }
13782
13783         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13784
13785         if (debug)
13786         {
13787                 R_DrawDebugModel();
13788                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13789                 return;
13790         }
13791
13792         rsurface.lightmaptexture = NULL;
13793         rsurface.deluxemaptexture = NULL;
13794         rsurface.uselightmaptexture = false;
13795         rsurface.texture = NULL;
13796         rsurface.rtlight = NULL;
13797         numsurfacelist = 0;
13798         // add visible surfaces to draw list
13799         for (i = 0;i < model->nummodelsurfaces;i++)
13800         {
13801                 j = model->sortedmodelsurfaces[i];
13802                 if (r_refdef.viewcache.world_surfacevisible[j])
13803                         r_surfacelist[numsurfacelist++] = surfaces + j;
13804         }
13805         // update lightmaps if needed
13806         if (model->brushq1.firstrender)
13807         {
13808                 model->brushq1.firstrender = false;
13809                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13810                         if (update[j])
13811                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13812         }
13813         else if (update)
13814         {
13815                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13816                         if (r_refdef.viewcache.world_surfacevisible[j])
13817                                 if (update[j])
13818                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13819         }
13820         // don't do anything if there were no surfaces
13821         if (!numsurfacelist)
13822         {
13823                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13824                 return;
13825         }
13826         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13827
13828         // add to stats if desired
13829         if (r_speeds.integer && !skysurfaces && !depthonly)
13830         {
13831                 r_refdef.stats.world_surfaces += numsurfacelist;
13832                 for (j = 0;j < numsurfacelist;j++)
13833                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13834         }
13835
13836         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13837 }
13838
13839 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13840 {
13841         int i, j, endj, flagsmask;
13842         dp_model_t *model = ent->model;
13843         msurface_t *surfaces;
13844         unsigned char *update;
13845         int numsurfacelist = 0;
13846         if (model == NULL)
13847                 return;
13848
13849         if (r_maxsurfacelist < model->num_surfaces)
13850         {
13851                 r_maxsurfacelist = model->num_surfaces;
13852                 if (r_surfacelist)
13853                         Mem_Free((msurface_t **)r_surfacelist);
13854                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13855         }
13856
13857         // if the model is static it doesn't matter what value we give for
13858         // wantnormals and wanttangents, so this logic uses only rules applicable
13859         // to a model, knowing that they are meaningless otherwise
13860         if (ent == r_refdef.scene.worldentity)
13861                 RSurf_ActiveWorldEntity();
13862         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13863                 RSurf_ActiveModelEntity(ent, false, false, false);
13864         else if (prepass)
13865                 RSurf_ActiveModelEntity(ent, true, true, true);
13866         else if (depthonly)
13867         {
13868                 switch (vid.renderpath)
13869                 {
13870                 case RENDERPATH_GL20:
13871                 case RENDERPATH_D3D9:
13872                 case RENDERPATH_D3D10:
13873                 case RENDERPATH_D3D11:
13874                 case RENDERPATH_SOFT:
13875                 case RENDERPATH_GLES2:
13876                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13877                         break;
13878                 case RENDERPATH_GL13:
13879                 case RENDERPATH_GL11:
13880                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13881                         break;
13882                 }
13883         }
13884         else
13885         {
13886                 switch (vid.renderpath)
13887                 {
13888                 case RENDERPATH_GL20:
13889                 case RENDERPATH_D3D9:
13890                 case RENDERPATH_D3D10:
13891                 case RENDERPATH_D3D11:
13892                 case RENDERPATH_SOFT:
13893                 case RENDERPATH_GLES2:
13894                         RSurf_ActiveModelEntity(ent, true, true, false);
13895                         break;
13896                 case RENDERPATH_GL13:
13897                 case RENDERPATH_GL11:
13898                         RSurf_ActiveModelEntity(ent, true, false, false);
13899                         break;
13900                 }
13901         }
13902
13903         surfaces = model->data_surfaces;
13904         update = model->brushq1.lightmapupdateflags;
13905
13906         // update light styles
13907         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13908         {
13909                 model_brush_lightstyleinfo_t *style;
13910                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13911                 {
13912                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13913                         {
13914                                 int *list = style->surfacelist;
13915                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13916                                 for (j = 0;j < style->numsurfaces;j++)
13917                                         update[list[j]] = true;
13918                         }
13919                 }
13920         }
13921
13922         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13923
13924         if (debug)
13925         {
13926                 R_DrawDebugModel();
13927                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13928                 return;
13929         }
13930
13931         rsurface.lightmaptexture = NULL;
13932         rsurface.deluxemaptexture = NULL;
13933         rsurface.uselightmaptexture = false;
13934         rsurface.texture = NULL;
13935         rsurface.rtlight = NULL;
13936         numsurfacelist = 0;
13937         // add visible surfaces to draw list
13938         for (i = 0;i < model->nummodelsurfaces;i++)
13939                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13940         // don't do anything if there were no surfaces
13941         if (!numsurfacelist)
13942         {
13943                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13944                 return;
13945         }
13946         // update lightmaps if needed
13947         if (update)
13948         {
13949                 int updated = 0;
13950                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13951                 {
13952                         if (update[j])
13953                         {
13954                                 updated++;
13955                                 R_BuildLightMap(ent, surfaces + j);
13956                         }
13957                 }
13958         }
13959         if (update)
13960                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13961                         if (update[j])
13962                                 R_BuildLightMap(ent, surfaces + j);
13963         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13964
13965         // add to stats if desired
13966         if (r_speeds.integer && !skysurfaces && !depthonly)
13967         {
13968                 r_refdef.stats.entities_surfaces += numsurfacelist;
13969                 for (j = 0;j < numsurfacelist;j++)
13970                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
13971         }
13972
13973         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13974 }
13975
13976 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
13977 {
13978         static texture_t texture;
13979         static msurface_t surface;
13980         const msurface_t *surfacelist = &surface;
13981
13982         // fake enough texture and surface state to render this geometry
13983
13984         texture.update_lastrenderframe = -1; // regenerate this texture
13985         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
13986         texture.currentskinframe = skinframe;
13987         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
13988         texture.offsetmapping = OFFSETMAPPING_OFF;
13989         texture.offsetscale = 1;
13990         texture.specularscalemod = 1;
13991         texture.specularpowermod = 1;
13992
13993         surface.texture = &texture;
13994         surface.num_triangles = numtriangles;
13995         surface.num_firsttriangle = firsttriangle;
13996         surface.num_vertices = numvertices;
13997         surface.num_firstvertex = firstvertex;
13998
13999         // now render it
14000         rsurface.texture = R_GetCurrentTexture(surface.texture);
14001         rsurface.lightmaptexture = NULL;
14002         rsurface.deluxemaptexture = NULL;
14003         rsurface.uselightmaptexture = false;
14004         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14005 }
14006
14007 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)
14008 {
14009         static msurface_t surface;
14010         const msurface_t *surfacelist = &surface;
14011
14012         // fake enough texture and surface state to render this geometry
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 }