]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
r_viewscale now works (with or without r_viewfbo), this allows reduced
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
121
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130
131 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
132 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
133
134 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
139
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146
147 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)"};
148 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
149 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
150 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
151 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
152 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
153 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
154 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)"};
155 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)"};
156 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)"};
157 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)"};
158 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)"};
159 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)"};
160 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)"};
161 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)"};
162
163 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)"};
164 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
165 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"};
166 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
167 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
168 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
169
170 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
171 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
172 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
173 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
174
175 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
176 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
177 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
178 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
179 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
180 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
181 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
182
183 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
184 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
185 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
186 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)"};
187 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
188 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
189 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
190 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
191 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
192 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
193
194 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"};
195
196 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"};
197
198 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
199
200 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
201 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"};
202 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
203 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
204 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
205 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
206 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)"};
207 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
208 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
209
210 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
211 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"};
212
213 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
214
215 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)"};
216
217 extern cvar_t v_glslgamma;
218
219 extern qboolean v_flipped_state;
220
221 static struct r_bloomstate_s
222 {
223         qboolean enabled;
224         qboolean hdr;
225
226         int bloomwidth, bloomheight;
227
228         textype_t texturetype;
229         int viewfbo; // used to check if r_viewfbo cvar has changed
230
231         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
232         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
233         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
234
235         int screentexturewidth, screentextureheight;
236         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
237
238         int bloomtexturewidth, bloomtextureheight;
239         rtexture_t *texture_bloom;
240
241         // arrays for rendering the screen passes
242         float screentexcoord2f[8];
243         float bloomtexcoord2f[8];
244         float offsettexcoord2f[8];
245
246         r_viewport_t viewport;
247 }
248 r_bloomstate;
249
250 r_waterstate_t r_waterstate;
251
252 /// shadow volume bsp struct with automatically growing nodes buffer
253 svbsp_t r_svbsp;
254
255 rtexture_t *r_texture_blanknormalmap;
256 rtexture_t *r_texture_white;
257 rtexture_t *r_texture_grey128;
258 rtexture_t *r_texture_black;
259 rtexture_t *r_texture_notexture;
260 rtexture_t *r_texture_whitecube;
261 rtexture_t *r_texture_normalizationcube;
262 rtexture_t *r_texture_fogattenuation;
263 rtexture_t *r_texture_fogheighttexture;
264 rtexture_t *r_texture_gammaramps;
265 unsigned int r_texture_gammaramps_serial;
266 //rtexture_t *r_texture_fogintensity;
267 rtexture_t *r_texture_reflectcube;
268
269 // TODO: hash lookups?
270 typedef struct cubemapinfo_s
271 {
272         char basename[64];
273         rtexture_t *texture;
274 }
275 cubemapinfo_t;
276
277 int r_texture_numcubemaps;
278 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
279
280 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
281 unsigned int r_numqueries;
282 unsigned int r_maxqueries;
283
284 typedef struct r_qwskincache_s
285 {
286         char name[MAX_QPATH];
287         skinframe_t *skinframe;
288 }
289 r_qwskincache_t;
290
291 static r_qwskincache_t *r_qwskincache;
292 static int r_qwskincache_size;
293
294 /// vertex coordinates for a quad that covers the screen exactly
295 extern const float r_screenvertex3f[12];
296 extern const float r_d3dscreenvertex3f[12];
297 const float r_screenvertex3f[12] =
298 {
299         0, 0, 0,
300         1, 0, 0,
301         1, 1, 0,
302         0, 1, 0
303 };
304 const float r_d3dscreenvertex3f[12] =
305 {
306         0, 1, 0,
307         1, 1, 0,
308         1, 0, 0,
309         0, 0, 0
310 };
311
312 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
313 {
314         int i;
315         for (i = 0;i < verts;i++)
316         {
317                 out[0] = in[0] * r;
318                 out[1] = in[1] * g;
319                 out[2] = in[2] * b;
320                 out[3] = in[3];
321                 in += 4;
322                 out += 4;
323         }
324 }
325
326 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
327 {
328         int i;
329         for (i = 0;i < verts;i++)
330         {
331                 out[0] = r;
332                 out[1] = g;
333                 out[2] = b;
334                 out[3] = a;
335                 out += 4;
336         }
337 }
338
339 // FIXME: move this to client?
340 void FOG_clear(void)
341 {
342         if (gamemode == GAME_NEHAHRA)
343         {
344                 Cvar_Set("gl_fogenable", "0");
345                 Cvar_Set("gl_fogdensity", "0.2");
346                 Cvar_Set("gl_fogred", "0.3");
347                 Cvar_Set("gl_foggreen", "0.3");
348                 Cvar_Set("gl_fogblue", "0.3");
349         }
350         r_refdef.fog_density = 0;
351         r_refdef.fog_red = 0;
352         r_refdef.fog_green = 0;
353         r_refdef.fog_blue = 0;
354         r_refdef.fog_alpha = 1;
355         r_refdef.fog_start = 0;
356         r_refdef.fog_end = 16384;
357         r_refdef.fog_height = 1<<30;
358         r_refdef.fog_fadedepth = 128;
359         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
360 }
361
362 static void R_BuildBlankTextures(void)
363 {
364         unsigned char data[4];
365         data[2] = 128; // normal X
366         data[1] = 128; // normal Y
367         data[0] = 255; // normal Z
368         data[3] = 128; // height
369         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 255;
371         data[1] = 255;
372         data[2] = 255;
373         data[3] = 255;
374         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 128;
376         data[1] = 128;
377         data[2] = 128;
378         data[3] = 255;
379         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 0;
381         data[1] = 0;
382         data[2] = 0;
383         data[3] = 255;
384         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildNoTexture(void)
388 {
389         int x, y;
390         unsigned char pix[16][16][4];
391         // this makes a light grey/dark grey checkerboard texture
392         for (y = 0;y < 16;y++)
393         {
394                 for (x = 0;x < 16;x++)
395                 {
396                         if ((y < 8) ^ (x < 8))
397                         {
398                                 pix[y][x][0] = 128;
399                                 pix[y][x][1] = 128;
400                                 pix[y][x][2] = 128;
401                                 pix[y][x][3] = 255;
402                         }
403                         else
404                         {
405                                 pix[y][x][0] = 64;
406                                 pix[y][x][1] = 64;
407                                 pix[y][x][2] = 64;
408                                 pix[y][x][3] = 255;
409                         }
410                 }
411         }
412         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
413 }
414
415 static void R_BuildWhiteCube(void)
416 {
417         unsigned char data[6*1*1*4];
418         memset(data, 255, sizeof(data));
419         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
420 }
421
422 static void R_BuildNormalizationCube(void)
423 {
424         int x, y, side;
425         vec3_t v;
426         vec_t s, t, intensity;
427 #define NORMSIZE 64
428         unsigned char *data;
429         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
430         for (side = 0;side < 6;side++)
431         {
432                 for (y = 0;y < NORMSIZE;y++)
433                 {
434                         for (x = 0;x < NORMSIZE;x++)
435                         {
436                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
437                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
438                                 switch(side)
439                                 {
440                                 default:
441                                 case 0:
442                                         v[0] = 1;
443                                         v[1] = -t;
444                                         v[2] = -s;
445                                         break;
446                                 case 1:
447                                         v[0] = -1;
448                                         v[1] = -t;
449                                         v[2] = s;
450                                         break;
451                                 case 2:
452                                         v[0] = s;
453                                         v[1] = 1;
454                                         v[2] = t;
455                                         break;
456                                 case 3:
457                                         v[0] = s;
458                                         v[1] = -1;
459                                         v[2] = -t;
460                                         break;
461                                 case 4:
462                                         v[0] = s;
463                                         v[1] = -t;
464                                         v[2] = 1;
465                                         break;
466                                 case 5:
467                                         v[0] = -s;
468                                         v[1] = -t;
469                                         v[2] = -1;
470                                         break;
471                                 }
472                                 intensity = 127.0f / sqrt(DotProduct(v, v));
473                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
474                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
475                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
476                                 data[((side*64+y)*64+x)*4+3] = 255;
477                         }
478                 }
479         }
480         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
481         Mem_Free(data);
482 }
483
484 static void R_BuildFogTexture(void)
485 {
486         int x, b;
487 #define FOGWIDTH 256
488         unsigned char data1[FOGWIDTH][4];
489         //unsigned char data2[FOGWIDTH][4];
490         double d, r, alpha;
491
492         r_refdef.fogmasktable_start = r_refdef.fog_start;
493         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
494         r_refdef.fogmasktable_range = r_refdef.fogrange;
495         r_refdef.fogmasktable_density = r_refdef.fog_density;
496
497         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
498         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
499         {
500                 d = (x * r - r_refdef.fogmasktable_start);
501                 if(developer_extra.integer)
502                         Con_DPrintf("%f ", d);
503                 d = max(0, d);
504                 if (r_fog_exp2.integer)
505                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
506                 else
507                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
508                 if(developer_extra.integer)
509                         Con_DPrintf(" : %f ", alpha);
510                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
511                 if(developer_extra.integer)
512                         Con_DPrintf(" = %f\n", alpha);
513                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
514         }
515
516         for (x = 0;x < FOGWIDTH;x++)
517         {
518                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
519                 data1[x][0] = b;
520                 data1[x][1] = b;
521                 data1[x][2] = b;
522                 data1[x][3] = 255;
523                 //data2[x][0] = 255 - b;
524                 //data2[x][1] = 255 - b;
525                 //data2[x][2] = 255 - b;
526                 //data2[x][3] = 255;
527         }
528         if (r_texture_fogattenuation)
529         {
530                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
531                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
532         }
533         else
534         {
535                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
536                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
537         }
538 }
539
540 static void R_BuildFogHeightTexture(void)
541 {
542         unsigned char *inpixels;
543         int size;
544         int x;
545         int y;
546         int j;
547         float c[4];
548         float f;
549         inpixels = NULL;
550         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
551         if (r_refdef.fogheighttexturename[0])
552                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
553         if (!inpixels)
554         {
555                 r_refdef.fog_height_tablesize = 0;
556                 if (r_texture_fogheighttexture)
557                         R_FreeTexture(r_texture_fogheighttexture);
558                 r_texture_fogheighttexture = NULL;
559                 if (r_refdef.fog_height_table2d)
560                         Mem_Free(r_refdef.fog_height_table2d);
561                 r_refdef.fog_height_table2d = NULL;
562                 if (r_refdef.fog_height_table1d)
563                         Mem_Free(r_refdef.fog_height_table1d);
564                 r_refdef.fog_height_table1d = NULL;
565                 return;
566         }
567         size = image_width;
568         r_refdef.fog_height_tablesize = size;
569         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
570         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
571         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
572         Mem_Free(inpixels);
573         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
574         // average fog color table accounting for every fog layer between a point
575         // and the camera.  (Note: attenuation is handled separately!)
576         for (y = 0;y < size;y++)
577         {
578                 for (x = 0;x < size;x++)
579                 {
580                         Vector4Clear(c);
581                         f = 0;
582                         if (x < y)
583                         {
584                                 for (j = x;j <= y;j++)
585                                 {
586                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
587                                         f++;
588                                 }
589                         }
590                         else
591                         {
592                                 for (j = x;j >= y;j--)
593                                 {
594                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
595                                         f++;
596                                 }
597                         }
598                         f = 1.0f / f;
599                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
600                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
601                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
602                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
603                 }
604         }
605         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
606 }
607
608 //=======================================================================================================================================================
609
610 static const char *builtinshaderstring =
611 #include "shader_glsl.h"
612 ;
613
614 const char *builtinhlslshaderstring =
615 #include "shader_hlsl.h"
616 ;
617
618 char *glslshaderstring = NULL;
619 char *hlslshaderstring = NULL;
620
621 //=======================================================================================================================================================
622
623 typedef struct shaderpermutationinfo_s
624 {
625         const char *pretext;
626         const char *name;
627 }
628 shaderpermutationinfo_t;
629
630 typedef struct shadermodeinfo_s
631 {
632         const char *vertexfilename;
633         const char *geometryfilename;
634         const char *fragmentfilename;
635         const char *pretext;
636         const char *name;
637 }
638 shadermodeinfo_t;
639
640 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
641 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
642 {
643         {"#define USEDIFFUSE\n", " diffuse"},
644         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
645         {"#define USEVIEWTINT\n", " viewtint"},
646         {"#define USECOLORMAPPING\n", " colormapping"},
647         {"#define USESATURATION\n", " saturation"},
648         {"#define USEFOGINSIDE\n", " foginside"},
649         {"#define USEFOGOUTSIDE\n", " fogoutside"},
650         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
651         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
652         {"#define USEGAMMARAMPS\n", " gammaramps"},
653         {"#define USECUBEFILTER\n", " cubefilter"},
654         {"#define USEGLOW\n", " glow"},
655         {"#define USEBLOOM\n", " bloom"},
656         {"#define USESPECULAR\n", " specular"},
657         {"#define USEPOSTPROCESSING\n", " postprocessing"},
658         {"#define USEREFLECTION\n", " reflection"},
659         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
660         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
661         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
662         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
663         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
664         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
665         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
666         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
667         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
668         {"#define USEALPHAKILL\n", " alphakill"},
669         {"#define USEREFLECTCUBE\n", " reflectcube"},
670         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
671         {"#define USEBOUNCEGRID\n", " bouncegrid"},
672         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
673 };
674
675 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
676 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
677 {
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
680         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
694 };
695
696 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
697 {
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
714 };
715
716 struct r_glsl_permutation_s;
717 typedef struct r_glsl_permutation_s
718 {
719         /// hash lookup data
720         struct r_glsl_permutation_s *hashnext;
721         unsigned int mode;
722         unsigned int permutation;
723
724         /// indicates if we have tried compiling this permutation already
725         qboolean compiled;
726         /// 0 if compilation failed
727         int program;
728         // texture units assigned to each detected uniform
729         int tex_Texture_First;
730         int tex_Texture_Second;
731         int tex_Texture_GammaRamps;
732         int tex_Texture_Normal;
733         int tex_Texture_Color;
734         int tex_Texture_Gloss;
735         int tex_Texture_Glow;
736         int tex_Texture_SecondaryNormal;
737         int tex_Texture_SecondaryColor;
738         int tex_Texture_SecondaryGloss;
739         int tex_Texture_SecondaryGlow;
740         int tex_Texture_Pants;
741         int tex_Texture_Shirt;
742         int tex_Texture_FogHeightTexture;
743         int tex_Texture_FogMask;
744         int tex_Texture_Lightmap;
745         int tex_Texture_Deluxemap;
746         int tex_Texture_Attenuation;
747         int tex_Texture_Cube;
748         int tex_Texture_Refraction;
749         int tex_Texture_Reflection;
750         int tex_Texture_ShadowMap2D;
751         int tex_Texture_CubeProjection;
752         int tex_Texture_ScreenDepth;
753         int tex_Texture_ScreenNormalMap;
754         int tex_Texture_ScreenDiffuse;
755         int tex_Texture_ScreenSpecular;
756         int tex_Texture_ReflectMask;
757         int tex_Texture_ReflectCube;
758         int tex_Texture_BounceGrid;
759         /// locations of detected uniforms in program object, or -1 if not found
760         int loc_Texture_First;
761         int loc_Texture_Second;
762         int loc_Texture_GammaRamps;
763         int loc_Texture_Normal;
764         int loc_Texture_Color;
765         int loc_Texture_Gloss;
766         int loc_Texture_Glow;
767         int loc_Texture_SecondaryNormal;
768         int loc_Texture_SecondaryColor;
769         int loc_Texture_SecondaryGloss;
770         int loc_Texture_SecondaryGlow;
771         int loc_Texture_Pants;
772         int loc_Texture_Shirt;
773         int loc_Texture_FogHeightTexture;
774         int loc_Texture_FogMask;
775         int loc_Texture_Lightmap;
776         int loc_Texture_Deluxemap;
777         int loc_Texture_Attenuation;
778         int loc_Texture_Cube;
779         int loc_Texture_Refraction;
780         int loc_Texture_Reflection;
781         int loc_Texture_ShadowMap2D;
782         int loc_Texture_CubeProjection;
783         int loc_Texture_ScreenDepth;
784         int loc_Texture_ScreenNormalMap;
785         int loc_Texture_ScreenDiffuse;
786         int loc_Texture_ScreenSpecular;
787         int loc_Texture_ReflectMask;
788         int loc_Texture_ReflectCube;
789         int loc_Texture_BounceGrid;
790         int loc_Alpha;
791         int loc_BloomBlur_Parameters;
792         int loc_ClientTime;
793         int loc_Color_Ambient;
794         int loc_Color_Diffuse;
795         int loc_Color_Specular;
796         int loc_Color_Glow;
797         int loc_Color_Pants;
798         int loc_Color_Shirt;
799         int loc_DeferredColor_Ambient;
800         int loc_DeferredColor_Diffuse;
801         int loc_DeferredColor_Specular;
802         int loc_DeferredMod_Diffuse;
803         int loc_DeferredMod_Specular;
804         int loc_DistortScaleRefractReflect;
805         int loc_EyePosition;
806         int loc_FogColor;
807         int loc_FogHeightFade;
808         int loc_FogPlane;
809         int loc_FogPlaneViewDist;
810         int loc_FogRangeRecip;
811         int loc_LightColor;
812         int loc_LightDir;
813         int loc_LightPosition;
814         int loc_OffsetMapping_ScaleSteps;
815         int loc_PixelSize;
816         int loc_ReflectColor;
817         int loc_ReflectFactor;
818         int loc_ReflectOffset;
819         int loc_RefractColor;
820         int loc_Saturation;
821         int loc_ScreenCenterRefractReflect;
822         int loc_ScreenScaleRefractReflect;
823         int loc_ScreenToDepth;
824         int loc_ShadowMap_Parameters;
825         int loc_ShadowMap_TextureScale;
826         int loc_SpecularPower;
827         int loc_UserVec1;
828         int loc_UserVec2;
829         int loc_UserVec3;
830         int loc_UserVec4;
831         int loc_ViewTintColor;
832         int loc_ViewToLight;
833         int loc_ModelToLight;
834         int loc_TexMatrix;
835         int loc_BackgroundTexMatrix;
836         int loc_ModelViewProjectionMatrix;
837         int loc_ModelViewMatrix;
838         int loc_PixelToScreenTexCoord;
839         int loc_ModelToReflectCube;
840         int loc_ShadowMapMatrix;
841         int loc_BloomColorSubtract;
842         int loc_NormalmapScrollBlend;
843         int loc_BounceGridMatrix;
844         int loc_BounceGridIntensity;
845 }
846 r_glsl_permutation_t;
847
848 #define SHADERPERMUTATION_HASHSIZE 256
849
850
851 // non-degradable "lightweight" shader parameters to keep the permutations simpler
852 // these can NOT degrade! only use for simple stuff
853 enum
854 {
855         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
856         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
857         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
858         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
859         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
861         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
862 };
863 #define SHADERSTATICPARMS_COUNT 7
864
865 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
866 static int shaderstaticparms_count = 0;
867
868 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
869 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
870 qboolean R_CompileShader_CheckStaticParms(void)
871 {
872         static int r_compileshader_staticparms_save[1];
873         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
874         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
875
876         // detect all
877         if (r_glsl_saturation_redcompensate.integer)
878                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
879         if (r_glsl_vertextextureblend_usebothalphas.integer)
880                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
881         if (r_shadow_glossexact.integer)
882                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
883         if (r_glsl_postprocess.integer)
884         {
885                 if (r_glsl_postprocess_uservec1_enable.integer)
886                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
887                 if (r_glsl_postprocess_uservec2_enable.integer)
888                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
889                 if (r_glsl_postprocess_uservec3_enable.integer)
890                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
891                 if (r_glsl_postprocess_uservec4_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
893         }
894         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
895 }
896
897 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
898         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
899                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
900         else \
901                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
902 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
903 {
904         shaderstaticparms_count = 0;
905
906         // emit all
907         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
908         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
909         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
910         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
911         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
912         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
914 }
915
916 /// information about each possible shader permutation
917 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
918 /// currently selected permutation
919 r_glsl_permutation_t *r_glsl_permutation;
920 /// storage for permutations linked in the hash table
921 memexpandablearray_t r_glsl_permutationarray;
922
923 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
924 {
925         //unsigned int hashdepth = 0;
926         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
927         r_glsl_permutation_t *p;
928         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
929         {
930                 if (p->mode == mode && p->permutation == permutation)
931                 {
932                         //if (hashdepth > 10)
933                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
934                         return p;
935                 }
936                 //hashdepth++;
937         }
938         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
939         p->mode = mode;
940         p->permutation = permutation;
941         p->hashnext = r_glsl_permutationhash[mode][hashindex];
942         r_glsl_permutationhash[mode][hashindex] = p;
943         //if (hashdepth > 10)
944         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
945         return p;
946 }
947
948 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
949 {
950         char *shaderstring;
951         if (!filename || !filename[0])
952                 return NULL;
953         if (!strcmp(filename, "glsl/default.glsl"))
954         {
955                 if (!glslshaderstring)
956                 {
957                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
958                         if (glslshaderstring)
959                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
960                         else
961                                 glslshaderstring = (char *)builtinshaderstring;
962                 }
963                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
964                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
965                 return shaderstring;
966         }
967         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
968         if (shaderstring)
969         {
970                 if (printfromdisknotice)
971                         Con_DPrintf("from disk %s... ", filename);
972                 return shaderstring;
973         }
974         return shaderstring;
975 }
976
977 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
978 {
979         int i;
980         int sampler;
981         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
982         char *vertexstring, *geometrystring, *fragmentstring;
983         char permutationname[256];
984         int vertstrings_count = 0;
985         int geomstrings_count = 0;
986         int fragstrings_count = 0;
987         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
988         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
989         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
990
991         if (p->compiled)
992                 return;
993         p->compiled = true;
994         p->program = 0;
995
996         permutationname[0] = 0;
997         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
998         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
999         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1000
1001         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1002
1003         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1004         if(vid.support.gl20shaders130)
1005         {
1006                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1007                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1008                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1009                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1010                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1011                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1012         }
1013
1014         // the first pretext is which type of shader to compile as
1015         // (later these will all be bound together as a program object)
1016         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1017         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1018         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1019
1020         // the second pretext is the mode (for example a light source)
1021         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1022         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1023         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1024         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1025
1026         // now add all the permutation pretexts
1027         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1028         {
1029                 if (permutation & (1<<i))
1030                 {
1031                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1032                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1033                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1034                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1035                 }
1036                 else
1037                 {
1038                         // keep line numbers correct
1039                         vertstrings_list[vertstrings_count++] = "\n";
1040                         geomstrings_list[geomstrings_count++] = "\n";
1041                         fragstrings_list[fragstrings_count++] = "\n";
1042                 }
1043         }
1044
1045         // add static parms
1046         R_CompileShader_AddStaticParms(mode, permutation);
1047         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1048         vertstrings_count += shaderstaticparms_count;
1049         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1050         geomstrings_count += shaderstaticparms_count;
1051         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1052         fragstrings_count += shaderstaticparms_count;
1053
1054         // now append the shader text itself
1055         vertstrings_list[vertstrings_count++] = vertexstring;
1056         geomstrings_list[geomstrings_count++] = geometrystring;
1057         fragstrings_list[fragstrings_count++] = fragmentstring;
1058
1059         // if any sources were NULL, clear the respective list
1060         if (!vertexstring)
1061                 vertstrings_count = 0;
1062         if (!geometrystring)
1063                 geomstrings_count = 0;
1064         if (!fragmentstring)
1065                 fragstrings_count = 0;
1066
1067         // compile the shader program
1068         if (vertstrings_count + geomstrings_count + fragstrings_count)
1069                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1070         if (p->program)
1071         {
1072                 CHECKGLERROR
1073                 qglUseProgram(p->program);CHECKGLERROR
1074                 // look up all the uniform variable names we care about, so we don't
1075                 // have to look them up every time we set them
1076
1077                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1078                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1079                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1080                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1081                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1082                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1083                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1084                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1085                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1086                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1087                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1088                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1089                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1090                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1091                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1092                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1093                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1094                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1095                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1096                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1097                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1098                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1099                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1100                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1101                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1102                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1103                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1104                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1105                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1106                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1107                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1108                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1109                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1110                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1111                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1112                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1113                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1114                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1115                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1116                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1117                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1118                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1119                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1120                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1121                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1122                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1123                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1124                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1125                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1126                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1127                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1128                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1129                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1130                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1131                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1132                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1133                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1134                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1135                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1136                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1137                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1138                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1139                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1140                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1141                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1142                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1143                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1144                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1145                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1146                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1147                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1148                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1149                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1150                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1151                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1152                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1153                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1154                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1155                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1156                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1157                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1158                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1159                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1160                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1161                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1162                 // initialize the samplers to refer to the texture units we use
1163                 p->tex_Texture_First = -1;
1164                 p->tex_Texture_Second = -1;
1165                 p->tex_Texture_GammaRamps = -1;
1166                 p->tex_Texture_Normal = -1;
1167                 p->tex_Texture_Color = -1;
1168                 p->tex_Texture_Gloss = -1;
1169                 p->tex_Texture_Glow = -1;
1170                 p->tex_Texture_SecondaryNormal = -1;
1171                 p->tex_Texture_SecondaryColor = -1;
1172                 p->tex_Texture_SecondaryGloss = -1;
1173                 p->tex_Texture_SecondaryGlow = -1;
1174                 p->tex_Texture_Pants = -1;
1175                 p->tex_Texture_Shirt = -1;
1176                 p->tex_Texture_FogHeightTexture = -1;
1177                 p->tex_Texture_FogMask = -1;
1178                 p->tex_Texture_Lightmap = -1;
1179                 p->tex_Texture_Deluxemap = -1;
1180                 p->tex_Texture_Attenuation = -1;
1181                 p->tex_Texture_Cube = -1;
1182                 p->tex_Texture_Refraction = -1;
1183                 p->tex_Texture_Reflection = -1;
1184                 p->tex_Texture_ShadowMap2D = -1;
1185                 p->tex_Texture_CubeProjection = -1;
1186                 p->tex_Texture_ScreenDepth = -1;
1187                 p->tex_Texture_ScreenNormalMap = -1;
1188                 p->tex_Texture_ScreenDiffuse = -1;
1189                 p->tex_Texture_ScreenSpecular = -1;
1190                 p->tex_Texture_ReflectMask = -1;
1191                 p->tex_Texture_ReflectCube = -1;
1192                 p->tex_Texture_BounceGrid = -1;
1193                 sampler = 0;
1194                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1195                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1196                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1197                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1198                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1199                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1200                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1201                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1202                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1203                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1204                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1205                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1206                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1207                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1208                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1209                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1210                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1211                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1212                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1213                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1214                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1215                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1216                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1217                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1218                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1219                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1220                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1221                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1222                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1223                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1224                 CHECKGLERROR
1225                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1226         }
1227         else
1228                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1229
1230         // free the strings
1231         if (vertexstring)
1232                 Mem_Free(vertexstring);
1233         if (geometrystring)
1234                 Mem_Free(geometrystring);
1235         if (fragmentstring)
1236                 Mem_Free(fragmentstring);
1237 }
1238
1239 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1240 {
1241         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1242         if (r_glsl_permutation != perm)
1243         {
1244                 r_glsl_permutation = perm;
1245                 if (!r_glsl_permutation->program)
1246                 {
1247                         if (!r_glsl_permutation->compiled)
1248                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1249                         if (!r_glsl_permutation->program)
1250                         {
1251                                 // remove features until we find a valid permutation
1252                                 int i;
1253                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1254                                 {
1255                                         // reduce i more quickly whenever it would not remove any bits
1256                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1257                                         if (!(permutation & j))
1258                                                 continue;
1259                                         permutation -= j;
1260                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1261                                         if (!r_glsl_permutation->compiled)
1262                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1263                                         if (r_glsl_permutation->program)
1264                                                 break;
1265                                 }
1266                                 if (i >= SHADERPERMUTATION_COUNT)
1267                                 {
1268                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1269                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1270                                         qglUseProgram(0);CHECKGLERROR
1271                                         return; // no bit left to clear, entire mode is broken
1272                                 }
1273                         }
1274                 }
1275                 CHECKGLERROR
1276                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1277         }
1278         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1279         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1280         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1281 }
1282
1283 #ifdef SUPPORTD3D
1284
1285 #ifdef SUPPORTD3D
1286 #include <d3d9.h>
1287 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1288 extern D3DCAPS9 vid_d3d9caps;
1289 #endif
1290
1291 struct r_hlsl_permutation_s;
1292 typedef struct r_hlsl_permutation_s
1293 {
1294         /// hash lookup data
1295         struct r_hlsl_permutation_s *hashnext;
1296         unsigned int mode;
1297         unsigned int permutation;
1298
1299         /// indicates if we have tried compiling this permutation already
1300         qboolean compiled;
1301         /// NULL if compilation failed
1302         IDirect3DVertexShader9 *vertexshader;
1303         IDirect3DPixelShader9 *pixelshader;
1304 }
1305 r_hlsl_permutation_t;
1306
1307 typedef enum D3DVSREGISTER_e
1308 {
1309         D3DVSREGISTER_TexMatrix = 0, // float4x4
1310         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1311         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1312         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1313         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1314         D3DVSREGISTER_ModelToLight = 20, // float4x4
1315         D3DVSREGISTER_EyePosition = 24,
1316         D3DVSREGISTER_FogPlane = 25,
1317         D3DVSREGISTER_LightDir = 26,
1318         D3DVSREGISTER_LightPosition = 27,
1319 }
1320 D3DVSREGISTER_t;
1321
1322 typedef enum D3DPSREGISTER_e
1323 {
1324         D3DPSREGISTER_Alpha = 0,
1325         D3DPSREGISTER_BloomBlur_Parameters = 1,
1326         D3DPSREGISTER_ClientTime = 2,
1327         D3DPSREGISTER_Color_Ambient = 3,
1328         D3DPSREGISTER_Color_Diffuse = 4,
1329         D3DPSREGISTER_Color_Specular = 5,
1330         D3DPSREGISTER_Color_Glow = 6,
1331         D3DPSREGISTER_Color_Pants = 7,
1332         D3DPSREGISTER_Color_Shirt = 8,
1333         D3DPSREGISTER_DeferredColor_Ambient = 9,
1334         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1335         D3DPSREGISTER_DeferredColor_Specular = 11,
1336         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1337         D3DPSREGISTER_DeferredMod_Specular = 13,
1338         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1339         D3DPSREGISTER_EyePosition = 15, // unused
1340         D3DPSREGISTER_FogColor = 16,
1341         D3DPSREGISTER_FogHeightFade = 17,
1342         D3DPSREGISTER_FogPlane = 18,
1343         D3DPSREGISTER_FogPlaneViewDist = 19,
1344         D3DPSREGISTER_FogRangeRecip = 20,
1345         D3DPSREGISTER_LightColor = 21,
1346         D3DPSREGISTER_LightDir = 22, // unused
1347         D3DPSREGISTER_LightPosition = 23,
1348         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1349         D3DPSREGISTER_PixelSize = 25,
1350         D3DPSREGISTER_ReflectColor = 26,
1351         D3DPSREGISTER_ReflectFactor = 27,
1352         D3DPSREGISTER_ReflectOffset = 28,
1353         D3DPSREGISTER_RefractColor = 29,
1354         D3DPSREGISTER_Saturation = 30,
1355         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1356         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1357         D3DPSREGISTER_ScreenToDepth = 33,
1358         D3DPSREGISTER_ShadowMap_Parameters = 34,
1359         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1360         D3DPSREGISTER_SpecularPower = 36,
1361         D3DPSREGISTER_UserVec1 = 37,
1362         D3DPSREGISTER_UserVec2 = 38,
1363         D3DPSREGISTER_UserVec3 = 39,
1364         D3DPSREGISTER_UserVec4 = 40,
1365         D3DPSREGISTER_ViewTintColor = 41,
1366         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1367         D3DPSREGISTER_BloomColorSubtract = 43,
1368         D3DPSREGISTER_ViewToLight = 44, // float4x4
1369         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1370         D3DPSREGISTER_NormalmapScrollBlend = 52,
1371         // next at 53
1372 }
1373 D3DPSREGISTER_t;
1374
1375 /// information about each possible shader permutation
1376 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1377 /// currently selected permutation
1378 r_hlsl_permutation_t *r_hlsl_permutation;
1379 /// storage for permutations linked in the hash table
1380 memexpandablearray_t r_hlsl_permutationarray;
1381
1382 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1383 {
1384         //unsigned int hashdepth = 0;
1385         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1386         r_hlsl_permutation_t *p;
1387         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1388         {
1389                 if (p->mode == mode && p->permutation == permutation)
1390                 {
1391                         //if (hashdepth > 10)
1392                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1393                         return p;
1394                 }
1395                 //hashdepth++;
1396         }
1397         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1398         p->mode = mode;
1399         p->permutation = permutation;
1400         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1401         r_hlsl_permutationhash[mode][hashindex] = p;
1402         //if (hashdepth > 10)
1403         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1404         return p;
1405 }
1406
1407 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1408 {
1409         char *shaderstring;
1410         if (!filename || !filename[0])
1411                 return NULL;
1412         if (!strcmp(filename, "hlsl/default.hlsl"))
1413         {
1414                 if (!hlslshaderstring)
1415                 {
1416                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1417                         if (hlslshaderstring)
1418                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1419                         else
1420                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1421                 }
1422                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1423                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1424                 return shaderstring;
1425         }
1426         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1427         if (shaderstring)
1428         {
1429                 if (printfromdisknotice)
1430                         Con_DPrintf("from disk %s... ", filename);
1431                 return shaderstring;
1432         }
1433         return shaderstring;
1434 }
1435
1436 #include <d3dx9.h>
1437 //#include <d3dx9shader.h>
1438 //#include <d3dx9mesh.h>
1439
1440 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1441 {
1442         DWORD *vsbin = NULL;
1443         DWORD *psbin = NULL;
1444         fs_offset_t vsbinsize;
1445         fs_offset_t psbinsize;
1446 //      IDirect3DVertexShader9 *vs = NULL;
1447 //      IDirect3DPixelShader9 *ps = NULL;
1448         ID3DXBuffer *vslog = NULL;
1449         ID3DXBuffer *vsbuffer = NULL;
1450         ID3DXConstantTable *vsconstanttable = NULL;
1451         ID3DXBuffer *pslog = NULL;
1452         ID3DXBuffer *psbuffer = NULL;
1453         ID3DXConstantTable *psconstanttable = NULL;
1454         int vsresult = 0;
1455         int psresult = 0;
1456         char temp[MAX_INPUTLINE];
1457         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1458         qboolean debugshader = gl_paranoid.integer != 0;
1459         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1460         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1461         if (!debugshader)
1462         {
1463                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1464                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1465         }
1466         if ((!vsbin && vertstring) || (!psbin && fragstring))
1467         {
1468                 const char* dllnames_d3dx9 [] =
1469                 {
1470                         "d3dx9_43.dll",
1471                         "d3dx9_42.dll",
1472                         "d3dx9_41.dll",
1473                         "d3dx9_40.dll",
1474                         "d3dx9_39.dll",
1475                         "d3dx9_38.dll",
1476                         "d3dx9_37.dll",
1477                         "d3dx9_36.dll",
1478                         "d3dx9_35.dll",
1479                         "d3dx9_34.dll",
1480                         "d3dx9_33.dll",
1481                         "d3dx9_32.dll",
1482                         "d3dx9_31.dll",
1483                         "d3dx9_30.dll",
1484                         "d3dx9_29.dll",
1485                         "d3dx9_28.dll",
1486                         "d3dx9_27.dll",
1487                         "d3dx9_26.dll",
1488                         "d3dx9_25.dll",
1489                         "d3dx9_24.dll",
1490                         NULL
1491                 };
1492                 dllhandle_t d3dx9_dll = NULL;
1493                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1494                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1495                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1496                 dllfunction_t d3dx9_dllfuncs[] =
1497                 {
1498                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1499                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1500                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1501                         {NULL, NULL}
1502                 };
1503                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1504                 {
1505                         DWORD shaderflags = 0;
1506                         if (debugshader)
1507                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1508                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1509                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1510                         if (vertstring && vertstring[0])
1511                         {
1512                                 if (debugshader)
1513                                 {
1514 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1515 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1516                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1517                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1518                                 }
1519                                 else
1520                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1521                                 if (vsbuffer)
1522                                 {
1523                                         vsbinsize = vsbuffer->GetBufferSize();
1524                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1525                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1526                                         vsbuffer->Release();
1527                                 }
1528                                 if (vslog)
1529                                 {
1530                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1531                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1532                                         vslog->Release();
1533                                 }
1534                         }
1535                         if (fragstring && fragstring[0])
1536                         {
1537                                 if (debugshader)
1538                                 {
1539 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1540 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1541                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1542                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1543                                 }
1544                                 else
1545                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1546                                 if (psbuffer)
1547                                 {
1548                                         psbinsize = psbuffer->GetBufferSize();
1549                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1550                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1551                                         psbuffer->Release();
1552                                 }
1553                                 if (pslog)
1554                                 {
1555                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1556                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1557                                         pslog->Release();
1558                                 }
1559                         }
1560                         Sys_UnloadLibrary(&d3dx9_dll);
1561                 }
1562                 else
1563                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1564         }
1565         if (vsbin && psbin)
1566         {
1567                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1568                 if (FAILED(vsresult))
1569                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1570                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1571                 if (FAILED(psresult))
1572                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1573         }
1574         // free the shader data
1575         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1576         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1577 }
1578
1579 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1580 {
1581         int i;
1582         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1583         int vertstring_length = 0;
1584         int geomstring_length = 0;
1585         int fragstring_length = 0;
1586         char *t;
1587         char *vertexstring, *geometrystring, *fragmentstring;
1588         char *vertstring, *geomstring, *fragstring;
1589         char permutationname[256];
1590         char cachename[256];
1591         int vertstrings_count = 0;
1592         int geomstrings_count = 0;
1593         int fragstrings_count = 0;
1594         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1595         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1597
1598         if (p->compiled)
1599                 return;
1600         p->compiled = true;
1601         p->vertexshader = NULL;
1602         p->pixelshader = NULL;
1603
1604         permutationname[0] = 0;
1605         cachename[0] = 0;
1606         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1607         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1608         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1609
1610         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1611         strlcat(cachename, "hlsl/", sizeof(cachename));
1612
1613         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1614         vertstrings_count = 0;
1615         geomstrings_count = 0;
1616         fragstrings_count = 0;
1617         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1618         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1619         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1620
1621         // the first pretext is which type of shader to compile as
1622         // (later these will all be bound together as a program object)
1623         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1624         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1625         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1626
1627         // the second pretext is the mode (for example a light source)
1628         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1629         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1630         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1631         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1632         strlcat(cachename, modeinfo->name, sizeof(cachename));
1633
1634         // now add all the permutation pretexts
1635         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1636         {
1637                 if (permutation & (1<<i))
1638                 {
1639                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1640                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1641                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1642                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1643                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1644                 }
1645                 else
1646                 {
1647                         // keep line numbers correct
1648                         vertstrings_list[vertstrings_count++] = "\n";
1649                         geomstrings_list[geomstrings_count++] = "\n";
1650                         fragstrings_list[fragstrings_count++] = "\n";
1651                 }
1652         }
1653
1654         // add static parms
1655         R_CompileShader_AddStaticParms(mode, permutation);
1656         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1657         vertstrings_count += shaderstaticparms_count;
1658         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1659         geomstrings_count += shaderstaticparms_count;
1660         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1661         fragstrings_count += shaderstaticparms_count;
1662
1663         // replace spaces in the cachename with _ characters
1664         for (i = 0;cachename[i];i++)
1665                 if (cachename[i] == ' ')
1666                         cachename[i] = '_';
1667
1668         // now append the shader text itself
1669         vertstrings_list[vertstrings_count++] = vertexstring;
1670         geomstrings_list[geomstrings_count++] = geometrystring;
1671         fragstrings_list[fragstrings_count++] = fragmentstring;
1672
1673         // if any sources were NULL, clear the respective list
1674         if (!vertexstring)
1675                 vertstrings_count = 0;
1676         if (!geometrystring)
1677                 geomstrings_count = 0;
1678         if (!fragmentstring)
1679                 fragstrings_count = 0;
1680
1681         vertstring_length = 0;
1682         for (i = 0;i < vertstrings_count;i++)
1683                 vertstring_length += strlen(vertstrings_list[i]);
1684         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1685         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1686                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1687
1688         geomstring_length = 0;
1689         for (i = 0;i < geomstrings_count;i++)
1690                 geomstring_length += strlen(geomstrings_list[i]);
1691         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1692         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1693                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1694
1695         fragstring_length = 0;
1696         for (i = 0;i < fragstrings_count;i++)
1697                 fragstring_length += strlen(fragstrings_list[i]);
1698         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1699         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1700                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1701
1702         // try to load the cached shader, or generate one
1703         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1704
1705         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1706                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1707         else
1708                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1709
1710         // free the strings
1711         if (vertstring)
1712                 Mem_Free(vertstring);
1713         if (geomstring)
1714                 Mem_Free(geomstring);
1715         if (fragstring)
1716                 Mem_Free(fragstring);
1717         if (vertexstring)
1718                 Mem_Free(vertexstring);
1719         if (geometrystring)
1720                 Mem_Free(geometrystring);
1721         if (fragmentstring)
1722                 Mem_Free(fragmentstring);
1723 }
1724
1725 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1726 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1727 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);}
1728 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);}
1729 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);}
1730 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);}
1731
1732 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1733 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1734 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);}
1735 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);}
1736 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);}
1737 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);}
1738
1739 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1740 {
1741         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1742         if (r_hlsl_permutation != perm)
1743         {
1744                 r_hlsl_permutation = perm;
1745                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1746                 {
1747                         if (!r_hlsl_permutation->compiled)
1748                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1749                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1750                         {
1751                                 // remove features until we find a valid permutation
1752                                 int i;
1753                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1754                                 {
1755                                         // reduce i more quickly whenever it would not remove any bits
1756                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1757                                         if (!(permutation & j))
1758                                                 continue;
1759                                         permutation -= j;
1760                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1761                                         if (!r_hlsl_permutation->compiled)
1762                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1763                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1764                                                 break;
1765                                 }
1766                                 if (i >= SHADERPERMUTATION_COUNT)
1767                                 {
1768                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1769                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1770                                         return; // no bit left to clear, entire mode is broken
1771                                 }
1772                         }
1773                 }
1774                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1775                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1776         }
1777         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1778         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1779         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1780 }
1781 #endif
1782
1783 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1784 {
1785         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1786         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1787         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1788         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1789 }
1790
1791 void R_GLSL_Restart_f(void)
1792 {
1793         unsigned int i, limit;
1794         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1795                 Mem_Free(glslshaderstring);
1796         glslshaderstring = NULL;
1797         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1798                 Mem_Free(hlslshaderstring);
1799         hlslshaderstring = NULL;
1800         switch(vid.renderpath)
1801         {
1802         case RENDERPATH_D3D9:
1803 #ifdef SUPPORTD3D
1804                 {
1805                         r_hlsl_permutation_t *p;
1806                         r_hlsl_permutation = NULL;
1807                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1808                         for (i = 0;i < limit;i++)
1809                         {
1810                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1811                                 {
1812                                         if (p->vertexshader)
1813                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1814                                         if (p->pixelshader)
1815                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1816                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1817                                 }
1818                         }
1819                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1820                 }
1821 #endif
1822                 break;
1823         case RENDERPATH_D3D10:
1824                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1825                 break;
1826         case RENDERPATH_D3D11:
1827                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1828                 break;
1829         case RENDERPATH_GL20:
1830         case RENDERPATH_GLES2:
1831                 {
1832                         r_glsl_permutation_t *p;
1833                         r_glsl_permutation = NULL;
1834                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1835                         for (i = 0;i < limit;i++)
1836                         {
1837                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1838                                 {
1839                                         GL_Backend_FreeProgram(p->program);
1840                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1841                                 }
1842                         }
1843                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1844                 }
1845                 break;
1846         case RENDERPATH_GL13:
1847         case RENDERPATH_GL11:
1848                 break;
1849         case RENDERPATH_SOFT:
1850                 break;
1851         }
1852 }
1853
1854 void R_GLSL_DumpShader_f(void)
1855 {
1856         int i;
1857         qfile_t *file;
1858
1859         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1860         if (file)
1861         {
1862                 FS_Print(file, "/* The engine may define the following macros:\n");
1863                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1864                 for (i = 0;i < SHADERMODE_COUNT;i++)
1865                         FS_Print(file, glslshadermodeinfo[i].pretext);
1866                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1867                         FS_Print(file, shaderpermutationinfo[i].pretext);
1868                 FS_Print(file, "*/\n");
1869                 FS_Print(file, builtinshaderstring);
1870                 FS_Close(file);
1871                 Con_Printf("glsl/default.glsl written\n");
1872         }
1873         else
1874                 Con_Printf("failed to write to glsl/default.glsl\n");
1875
1876         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1877         if (file)
1878         {
1879                 FS_Print(file, "/* The engine may define the following macros:\n");
1880                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1881                 for (i = 0;i < SHADERMODE_COUNT;i++)
1882                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1883                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1884                         FS_Print(file, shaderpermutationinfo[i].pretext);
1885                 FS_Print(file, "*/\n");
1886                 FS_Print(file, builtinhlslshaderstring);
1887                 FS_Close(file);
1888                 Con_Printf("hlsl/default.hlsl written\n");
1889         }
1890         else
1891                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1892 }
1893
1894 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1895 {
1896         if (!second)
1897                 texturemode = GL_MODULATE;
1898         switch (vid.renderpath)
1899         {
1900         case RENDERPATH_D3D9:
1901 #ifdef SUPPORTD3D
1902                 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))));
1903                 R_Mesh_TexBind(GL20TU_FIRST , first );
1904                 R_Mesh_TexBind(GL20TU_SECOND, second);
1905 #endif
1906                 break;
1907         case RENDERPATH_D3D10:
1908                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1909                 break;
1910         case RENDERPATH_D3D11:
1911                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1912                 break;
1913         case RENDERPATH_GL20:
1914         case RENDERPATH_GLES2:
1915                 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))));
1916                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1917                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1918                 break;
1919         case RENDERPATH_GL13:
1920                 R_Mesh_TexBind(0, first );
1921                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1922                 R_Mesh_TexBind(1, second);
1923                 if (second)
1924                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1925                 break;
1926         case RENDERPATH_GL11:
1927                 R_Mesh_TexBind(0, first );
1928                 break;
1929         case RENDERPATH_SOFT:
1930                 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))));
1931                 R_Mesh_TexBind(GL20TU_FIRST , first );
1932                 R_Mesh_TexBind(GL20TU_SECOND, second);
1933                 break;
1934         }
1935 }
1936
1937 void R_SetupShader_DepthOrShadow(void)
1938 {
1939         switch (vid.renderpath)
1940         {
1941         case RENDERPATH_D3D9:
1942 #ifdef SUPPORTD3D
1943                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1944 #endif
1945                 break;
1946         case RENDERPATH_D3D10:
1947                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1948                 break;
1949         case RENDERPATH_D3D11:
1950                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1951                 break;
1952         case RENDERPATH_GL20:
1953         case RENDERPATH_GLES2:
1954                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1955                 break;
1956         case RENDERPATH_GL13:
1957                 R_Mesh_TexBind(0, 0);
1958                 R_Mesh_TexBind(1, 0);
1959                 break;
1960         case RENDERPATH_GL11:
1961                 R_Mesh_TexBind(0, 0);
1962                 break;
1963         case RENDERPATH_SOFT:
1964                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1965                 break;
1966         }
1967 }
1968
1969 void R_SetupShader_ShowDepth(void)
1970 {
1971         switch (vid.renderpath)
1972         {
1973         case RENDERPATH_D3D9:
1974 #ifdef SUPPORTHLSL
1975                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1976 #endif
1977                 break;
1978         case RENDERPATH_D3D10:
1979                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1980                 break;
1981         case RENDERPATH_D3D11:
1982                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1983                 break;
1984         case RENDERPATH_GL20:
1985         case RENDERPATH_GLES2:
1986                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1987                 break;
1988         case RENDERPATH_GL13:
1989                 break;
1990         case RENDERPATH_GL11:
1991                 break;
1992         case RENDERPATH_SOFT:
1993                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1994                 break;
1995         }
1996 }
1997
1998 extern qboolean r_shadow_usingdeferredprepass;
1999 extern cvar_t r_shadow_deferred_8bitrange;
2000 extern rtexture_t *r_shadow_attenuationgradienttexture;
2001 extern rtexture_t *r_shadow_attenuation2dtexture;
2002 extern rtexture_t *r_shadow_attenuation3dtexture;
2003 extern qboolean r_shadow_usingshadowmap2d;
2004 extern qboolean r_shadow_usingshadowmaportho;
2005 extern float r_shadow_shadowmap_texturescale[2];
2006 extern float r_shadow_shadowmap_parameters[4];
2007 extern qboolean r_shadow_shadowmapvsdct;
2008 extern qboolean r_shadow_shadowmapsampler;
2009 extern int r_shadow_shadowmappcf;
2010 extern rtexture_t *r_shadow_shadowmap2dtexture;
2011 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2012 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2013 extern matrix4x4_t r_shadow_shadowmapmatrix;
2014 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2015 extern int r_shadow_prepass_width;
2016 extern int r_shadow_prepass_height;
2017 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2018 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2019 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2020 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2021 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2022
2023 #define BLENDFUNC_ALLOWS_COLORMOD      1
2024 #define BLENDFUNC_ALLOWS_FOG           2
2025 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2026 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2027 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2028 static int R_BlendFuncFlags(int src, int dst)
2029 {
2030         int r = 0;
2031
2032         // a blendfunc allows colormod if:
2033         // a) it can never keep the destination pixel invariant, or
2034         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2035         // this is to prevent unintended side effects from colormod
2036
2037         // a blendfunc allows fog if:
2038         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2039         // this is to prevent unintended side effects from fog
2040
2041         // these checks are the output of fogeval.pl
2042
2043         r |= BLENDFUNC_ALLOWS_COLORMOD;
2044         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2045         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2046         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2047         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2048         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2049         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2050         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2051         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2052         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2053         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2054         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2055         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2056         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2057         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2058         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2059         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2063         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2064         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2065
2066         return r;
2067 }
2068
2069 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)
2070 {
2071         // select a permutation of the lighting shader appropriate to this
2072         // combination of texture, entity, light source, and fogging, only use the
2073         // minimum features necessary to avoid wasting rendering time in the
2074         // fragment shader on features that are not being used
2075         unsigned int permutation = 0;
2076         unsigned int mode = 0;
2077         int blendfuncflags;
2078         static float dummy_colormod[3] = {1, 1, 1};
2079         float *colormod = rsurface.colormod;
2080         float m16f[16];
2081         matrix4x4_t tempmatrix;
2082         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2083         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2084                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2085         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2086                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2087         if (rsurfacepass == RSURFPASS_BACKGROUND)
2088         {
2089                 // distorted background
2090                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2091                 {
2092                         mode = SHADERMODE_WATER;
2093                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2094                         {
2095                                 // this is the right thing to do for wateralpha
2096                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2097                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2098                         }
2099                         else
2100                         {
2101                                 // this is the right thing to do for entity alpha
2102                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2103                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2104                         }
2105                 }
2106                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2107                 {
2108                         mode = SHADERMODE_REFRACTION;
2109                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2110                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2111                 }
2112                 else
2113                 {
2114                         mode = SHADERMODE_GENERIC;
2115                         permutation |= SHADERPERMUTATION_DIFFUSE;
2116                         GL_BlendFunc(GL_ONE, GL_ZERO);
2117                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2118                 }
2119         }
2120         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2121         {
2122                 if (r_glsl_offsetmapping.integer)
2123                 {
2124                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2125                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2126                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2127                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2128                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2129                         {
2130                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2131                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2132                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2133                         }
2134                 }
2135                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2136                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2137                 // normalmap (deferred prepass), may use alpha test on diffuse
2138                 mode = SHADERMODE_DEFERREDGEOMETRY;
2139                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2140                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2141                 GL_BlendFunc(GL_ONE, GL_ZERO);
2142                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2143         }
2144         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2145         {
2146                 if (r_glsl_offsetmapping.integer)
2147                 {
2148                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2149                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2150                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2151                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2152                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2153                         {
2154                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2155                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2156                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2157                         }
2158                 }
2159                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2160                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2161                 // light source
2162                 mode = SHADERMODE_LIGHTSOURCE;
2163                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2164                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2165                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2166                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2167                 if (diffusescale > 0)
2168                         permutation |= SHADERPERMUTATION_DIFFUSE;
2169                 if (specularscale > 0)
2170                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2171                 if (r_refdef.fogenabled)
2172                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2173                 if (rsurface.texture->colormapping)
2174                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2175                 if (r_shadow_usingshadowmap2d)
2176                 {
2177                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2178                         if(r_shadow_shadowmapvsdct)
2179                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2180
2181                         if (r_shadow_shadowmapsampler)
2182                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2183                         if (r_shadow_shadowmappcf > 1)
2184                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2185                         else if (r_shadow_shadowmappcf)
2186                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2187                 }
2188                 if (rsurface.texture->reflectmasktexture)
2189                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2190                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2191                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2192         }
2193         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2194         {
2195                 if (r_glsl_offsetmapping.integer)
2196                 {
2197                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2198                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2199                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2200                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2201                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2202                         {
2203                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2204                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2205                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2206                         }
2207                 }
2208                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2209                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2210                 // unshaded geometry (fullbright or ambient model lighting)
2211                 mode = SHADERMODE_FLATCOLOR;
2212                 ambientscale = diffusescale = specularscale = 0;
2213                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2214                         permutation |= SHADERPERMUTATION_GLOW;
2215                 if (r_refdef.fogenabled)
2216                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2217                 if (rsurface.texture->colormapping)
2218                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2219                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2220                 {
2221                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2222                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2223
2224                         if (r_shadow_shadowmapsampler)
2225                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2226                         if (r_shadow_shadowmappcf > 1)
2227                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2228                         else if (r_shadow_shadowmappcf)
2229                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2230                 }
2231                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2232                         permutation |= SHADERPERMUTATION_REFLECTION;
2233                 if (rsurface.texture->reflectmasktexture)
2234                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2235                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2236                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2237         }
2238         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2239         {
2240                 if (r_glsl_offsetmapping.integer)
2241                 {
2242                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2243                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2244                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2245                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2246                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2247                         {
2248                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2249                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2250                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2251                         }
2252                 }
2253                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2254                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2255                 // directional model lighting
2256                 mode = SHADERMODE_LIGHTDIRECTION;
2257                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258                         permutation |= SHADERPERMUTATION_GLOW;
2259                 permutation |= SHADERPERMUTATION_DIFFUSE;
2260                 if (specularscale > 0)
2261                         permutation |= SHADERPERMUTATION_SPECULAR;
2262                 if (r_refdef.fogenabled)
2263                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2264                 if (rsurface.texture->colormapping)
2265                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2266                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2267                 {
2268                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2269                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2270
2271                         if (r_shadow_shadowmapsampler)
2272                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2273                         if (r_shadow_shadowmappcf > 1)
2274                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2275                         else if (r_shadow_shadowmappcf)
2276                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2277                 }
2278                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2279                         permutation |= SHADERPERMUTATION_REFLECTION;
2280                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2281                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2282                 if (rsurface.texture->reflectmasktexture)
2283                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2284                 if (r_shadow_bouncegridtexture)
2285                 {
2286                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2287                         if (r_shadow_bouncegriddirectional)
2288                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2289                 }
2290                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2291                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2292         }
2293         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2294         {
2295                 if (r_glsl_offsetmapping.integer)
2296                 {
2297                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2298                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2299                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2300                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2301                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2302                         {
2303                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2304                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2305                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2306                         }
2307                 }
2308                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2309                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2310                 // ambient model lighting
2311                 mode = SHADERMODE_LIGHTDIRECTION;
2312                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2313                         permutation |= SHADERPERMUTATION_GLOW;
2314                 if (r_refdef.fogenabled)
2315                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2316                 if (rsurface.texture->colormapping)
2317                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2318                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2319                 {
2320                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2321                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2322
2323                         if (r_shadow_shadowmapsampler)
2324                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2325                         if (r_shadow_shadowmappcf > 1)
2326                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2327                         else if (r_shadow_shadowmappcf)
2328                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2329                 }
2330                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2331                         permutation |= SHADERPERMUTATION_REFLECTION;
2332                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2333                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2334                 if (rsurface.texture->reflectmasktexture)
2335                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2336                 if (r_shadow_bouncegridtexture)
2337                 {
2338                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2339                         if (r_shadow_bouncegriddirectional)
2340                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2341                 }
2342                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2343                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2344         }
2345         else
2346         {
2347                 if (r_glsl_offsetmapping.integer)
2348                 {
2349                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2350                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2351                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2352                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2353                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2354                         {
2355                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2356                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2357                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2358                         }
2359                 }
2360                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2361                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2362                 // lightmapped wall
2363                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2364                         permutation |= SHADERPERMUTATION_GLOW;
2365                 if (r_refdef.fogenabled)
2366                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2367                 if (rsurface.texture->colormapping)
2368                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2369                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2370                 {
2371                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2372                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2373
2374                         if (r_shadow_shadowmapsampler)
2375                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2376                         if (r_shadow_shadowmappcf > 1)
2377                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2378                         else if (r_shadow_shadowmappcf)
2379                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2380                 }
2381                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2382                         permutation |= SHADERPERMUTATION_REFLECTION;
2383                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2384                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2385                 if (rsurface.texture->reflectmasktexture)
2386                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2387                 if (FAKELIGHT_ENABLED)
2388                 {
2389                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2390                         mode = SHADERMODE_FAKELIGHT;
2391                         permutation |= SHADERPERMUTATION_DIFFUSE;
2392                         if (specularscale > 0)
2393                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2394                 }
2395                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2396                 {
2397                         // deluxemapping (light direction texture)
2398                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2399                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2400                         else
2401                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2402                         permutation |= SHADERPERMUTATION_DIFFUSE;
2403                         if (specularscale > 0)
2404                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2405                 }
2406                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2407                 {
2408                         // fake deluxemapping (uniform light direction in tangentspace)
2409                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2410                         permutation |= SHADERPERMUTATION_DIFFUSE;
2411                         if (specularscale > 0)
2412                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2413                 }
2414                 else if (rsurface.uselightmaptexture)
2415                 {
2416                         // ordinary lightmapping (q1bsp, q3bsp)
2417                         mode = SHADERMODE_LIGHTMAP;
2418                 }
2419                 else
2420                 {
2421                         // ordinary vertex coloring (q3bsp)
2422                         mode = SHADERMODE_VERTEXCOLOR;
2423                 }
2424                 if (r_shadow_bouncegridtexture)
2425                 {
2426                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2427                         if (r_shadow_bouncegriddirectional)
2428                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2429                 }
2430                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2431                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2432         }
2433         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2434                 colormod = dummy_colormod;
2435         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2436                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2437         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2438                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2439         switch(vid.renderpath)
2440         {
2441         case RENDERPATH_D3D9:
2442 #ifdef SUPPORTD3D
2443                 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);
2444                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2445                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2446                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2447                 if (mode == SHADERMODE_LIGHTSOURCE)
2448                 {
2449                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2450                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2451                 }
2452                 else
2453                 {
2454                         if (mode == SHADERMODE_LIGHTDIRECTION)
2455                         {
2456                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2457                         }
2458                 }
2459                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2460                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2461                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2462                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2463                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2464
2465                 if (mode == SHADERMODE_LIGHTSOURCE)
2466                 {
2467                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2468                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2469                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2470                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2471                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2472
2473                         // additive passes are only darkened by fog, not tinted
2474                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2475                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2476                 }
2477                 else
2478                 {
2479                         if (mode == SHADERMODE_FLATCOLOR)
2480                         {
2481                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2482                         }
2483                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2484                         {
2485                                 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]);
2486                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2487                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2488                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2489                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2490                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2491                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2492                         }
2493                         else
2494                         {
2495                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2496                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2497                                 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);
2498                                 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);
2499                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2500                         }
2501                         // additive passes are only darkened by fog, not tinted
2502                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2503                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2504                         else
2505                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2506                         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);
2507                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2508                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2509                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2510                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2511                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2512                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2513                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2514                         if (mode == SHADERMODE_WATER)
2515                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2516                 }
2517                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2518                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2519                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2520                 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));
2521                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2522                 if (rsurface.texture->pantstexture)
2523                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2524                 else
2525                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2526                 if (rsurface.texture->shirttexture)
2527                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2528                 else
2529                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2530                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2531                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2532                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2533                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2534                 hlslPSSetParameter3f(D3DPSREGISTER_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2535                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2536                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2537
2538                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2539                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2540                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2541                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2542                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2543                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2544                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2545                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2546                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2547                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2548                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2549                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2550                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2551                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2552                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2553                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2554                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2555                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2556                 {
2557                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2558                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2559                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2560                 }
2561                 else
2562                 {
2563                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2564                 }
2565 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2566 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2567                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2568                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2569                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2570                 {
2571                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2572                         if (rsurface.rtlight)
2573                         {
2574                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2575                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2576                         }
2577                 }
2578 #endif
2579                 break;
2580         case RENDERPATH_D3D10:
2581                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2582                 break;
2583         case RENDERPATH_D3D11:
2584                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2585                 break;
2586         case RENDERPATH_GL20:
2587         case RENDERPATH_GLES2:
2588                 if (!vid.useinterleavedarrays)
2589                 {
2590                         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);
2591                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2592                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2593                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2594                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2595                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2596                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2597                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2598                 }
2599                 else
2600                 {
2601                         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);
2602                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2603                 }
2604                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2605                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2606                 if (mode == SHADERMODE_LIGHTSOURCE)
2607                 {
2608                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2609                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2610                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2611                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2612                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2613                         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);
2614         
2615                         // additive passes are only darkened by fog, not tinted
2616                         if (r_glsl_permutation->loc_FogColor >= 0)
2617                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2618                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2619                 }
2620                 else
2621                 {
2622                         if (mode == SHADERMODE_FLATCOLOR)
2623                         {
2624                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2625                         }
2626                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2627                         {
2628                                 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]);
2629                                 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]);
2630                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2631                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2632                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2633                                 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]);
2634                                 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]);
2635                         }
2636                         else
2637                         {
2638                                 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]);
2639                                 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]);
2640                                 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);
2641                                 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);
2642                                 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);
2643                         }
2644                         // additive passes are only darkened by fog, not tinted
2645                         if (r_glsl_permutation->loc_FogColor >= 0)
2646                         {
2647                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2648                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2649                                 else
2650                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2651                         }
2652                         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);
2653                         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]);
2654                         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]);
2655                         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]);
2656                         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]);
2657                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2658                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2659                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2660                         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]);
2661                 }
2662                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2663                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2664                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2665                 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]);
2666                 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]);
2667
2668                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2669                 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));
2670                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2671                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2672                 {
2673                         if (rsurface.texture->pantstexture)
2674                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2675                         else
2676                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2677                 }
2678                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2679                 {
2680                         if (rsurface.texture->shirttexture)
2681                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2682                         else
2683                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2684                 }
2685                 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]);
2686                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2687                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2688                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2689                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform3f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2690                 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]);
2691                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2692                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2693                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2694
2695                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2696                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2697                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2698                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2699                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2700                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2701                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2702                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2703                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2704                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2705                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2706                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2707                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2708                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2709                 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);
2710                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2711                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2712                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2713                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2714                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2715                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2716                 {
2717                         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);
2718                         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);
2719                         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);
2720                 }
2721                 else
2722                 {
2723                         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);
2724                 }
2725                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2726                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2727                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2728                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2729                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2730                 {
2731                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2732                         if (rsurface.rtlight)
2733                         {
2734                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2735                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2736                         }
2737                 }
2738                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2739                 CHECKGLERROR
2740                 break;
2741         case RENDERPATH_GL13:
2742         case RENDERPATH_GL11:
2743                 break;
2744         case RENDERPATH_SOFT:
2745                 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);
2746                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2747                 R_SetupShader_SetPermutationSoft(mode, permutation);
2748                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2749                 if (mode == SHADERMODE_LIGHTSOURCE)
2750                 {
2751                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2752                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2753                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2754                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2755                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2756                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2757         
2758                         // additive passes are only darkened by fog, not tinted
2759                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2760                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2761                 }
2762                 else
2763                 {
2764                         if (mode == SHADERMODE_FLATCOLOR)
2765                         {
2766                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2767                         }
2768                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2769                         {
2770                                 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]);
2771                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2772                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2773                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2774                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2775                                 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]);
2776                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2777                         }
2778                         else
2779                         {
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2782                                 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);
2783                                 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);
2784                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2785                         }
2786                         // additive passes are only darkened by fog, not tinted
2787                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2788                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2789                         else
2790                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2791                         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);
2792                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2793                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2794                         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]);
2795                         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]);
2796                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2797                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2798                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2799                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2800                 }
2801                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2802                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2803                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2804                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2805                 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]);
2806
2807                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2808                 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));
2809                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2810                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2811                 {
2812                         if (rsurface.texture->pantstexture)
2813                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2814                         else
2815                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2816                 }
2817                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2818                 {
2819                         if (rsurface.texture->shirttexture)
2820                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2821                         else
2822                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2823                 }
2824                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2825                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2826                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2827                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2828                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2829                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2830                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2831
2832                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2833                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2834                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2835                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2836                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2837                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2838                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2839                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2840                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2841                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2842                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2843                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2844                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2845                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2846                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2847                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2848                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2849                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2850                 {
2851                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2852                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2853                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2854                 }
2855                 else
2856                 {
2857                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2858                 }
2859 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2860 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2861                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2862                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2863                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2864                 {
2865                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2866                         if (rsurface.rtlight)
2867                         {
2868                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2869                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2870                         }
2871                 }
2872                 break;
2873         }
2874 }
2875
2876 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2877 {
2878         // select a permutation of the lighting shader appropriate to this
2879         // combination of texture, entity, light source, and fogging, only use the
2880         // minimum features necessary to avoid wasting rendering time in the
2881         // fragment shader on features that are not being used
2882         unsigned int permutation = 0;
2883         unsigned int mode = 0;
2884         const float *lightcolorbase = rtlight->currentcolor;
2885         float ambientscale = rtlight->ambientscale;
2886         float diffusescale = rtlight->diffusescale;
2887         float specularscale = rtlight->specularscale;
2888         // this is the location of the light in view space
2889         vec3_t viewlightorigin;
2890         // this transforms from view space (camera) to light space (cubemap)
2891         matrix4x4_t viewtolight;
2892         matrix4x4_t lighttoview;
2893         float viewtolight16f[16];
2894         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2895         // light source
2896         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2897         if (rtlight->currentcubemap != r_texture_whitecube)
2898                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2899         if (diffusescale > 0)
2900                 permutation |= SHADERPERMUTATION_DIFFUSE;
2901         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2902                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2903         if (r_shadow_usingshadowmap2d)
2904         {
2905                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2906                 if (r_shadow_shadowmapvsdct)
2907                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2908
2909                 if (r_shadow_shadowmapsampler)
2910                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2911                 if (r_shadow_shadowmappcf > 1)
2912                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2913                 else if (r_shadow_shadowmappcf)
2914                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2915         }
2916         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2917         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2918         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2919         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2920         switch(vid.renderpath)
2921         {
2922         case RENDERPATH_D3D9:
2923 #ifdef SUPPORTD3D
2924                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2925                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2926                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2927                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2928                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2929                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2930                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2931                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2932                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2933                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2934                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2935
2936                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2937                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2938                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2939                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2940                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2941                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2942 #endif
2943                 break;
2944         case RENDERPATH_D3D10:
2945                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2946                 break;
2947         case RENDERPATH_D3D11:
2948                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2949                 break;
2950         case RENDERPATH_GL20:
2951         case RENDERPATH_GLES2:
2952                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2953                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2954                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2955                 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);
2956                 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);
2957                 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);
2958                 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]);
2959                 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]);
2960                 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));
2961                 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]);
2962                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2963
2964                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2965                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2966                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2967                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2968                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2969                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2970                 break;
2971         case RENDERPATH_GL13:
2972         case RENDERPATH_GL11:
2973                 break;
2974         case RENDERPATH_SOFT:
2975                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2976                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2977                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2978                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2979                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2980                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2981                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2982                 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]);
2983                 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));
2984                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2985                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2986
2987                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2988                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2989                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2990                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2991                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2992                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2993                 break;
2994         }
2995 }
2996
2997 #define SKINFRAME_HASH 1024
2998
2999 typedef struct
3000 {
3001         int loadsequence; // incremented each level change
3002         memexpandablearray_t array;
3003         skinframe_t *hash[SKINFRAME_HASH];
3004 }
3005 r_skinframe_t;
3006 r_skinframe_t r_skinframe;
3007
3008 void R_SkinFrame_PrepareForPurge(void)
3009 {
3010         r_skinframe.loadsequence++;
3011         // wrap it without hitting zero
3012         if (r_skinframe.loadsequence >= 200)
3013                 r_skinframe.loadsequence = 1;
3014 }
3015
3016 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3017 {
3018         if (!skinframe)
3019                 return;
3020         // mark the skinframe as used for the purging code
3021         skinframe->loadsequence = r_skinframe.loadsequence;
3022 }
3023
3024 void R_SkinFrame_Purge(void)
3025 {
3026         int i;
3027         skinframe_t *s;
3028         for (i = 0;i < SKINFRAME_HASH;i++)
3029         {
3030                 for (s = r_skinframe.hash[i];s;s = s->next)
3031                 {
3032                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3033                         {
3034                                 if (s->merged == s->base)
3035                                         s->merged = NULL;
3036                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3037                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3038                                 R_PurgeTexture(s->merged);s->merged = NULL;
3039                                 R_PurgeTexture(s->base  );s->base   = NULL;
3040                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3041                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3042                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3043                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3044                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3045                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3046                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3047                                 s->loadsequence = 0;
3048                         }
3049                 }
3050         }
3051 }
3052
3053 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3054         skinframe_t *item;
3055         char basename[MAX_QPATH];
3056
3057         Image_StripImageExtension(name, basename, sizeof(basename));
3058
3059         if( last == NULL ) {
3060                 int hashindex;
3061                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3062                 item = r_skinframe.hash[hashindex];
3063         } else {
3064                 item = last->next;
3065         }
3066
3067         // linearly search through the hash bucket
3068         for( ; item ; item = item->next ) {
3069                 if( !strcmp( item->basename, basename ) ) {
3070                         return item;
3071                 }
3072         }
3073         return NULL;
3074 }
3075
3076 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3077 {
3078         skinframe_t *item;
3079         int hashindex;
3080         char basename[MAX_QPATH];
3081
3082         Image_StripImageExtension(name, basename, sizeof(basename));
3083
3084         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3085         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3086                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3087                         break;
3088
3089         if (!item) {
3090                 rtexture_t *dyntexture;
3091                 // check whether its a dynamic texture
3092                 dyntexture = CL_GetDynTexture( basename );
3093                 if (!add && !dyntexture)
3094                         return NULL;
3095                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3096                 memset(item, 0, sizeof(*item));
3097                 strlcpy(item->basename, basename, sizeof(item->basename));
3098                 item->base = dyntexture; // either NULL or dyntexture handle
3099                 item->textureflags = textureflags;
3100                 item->comparewidth = comparewidth;
3101                 item->compareheight = compareheight;
3102                 item->comparecrc = comparecrc;
3103                 item->next = r_skinframe.hash[hashindex];
3104                 r_skinframe.hash[hashindex] = item;
3105         }
3106         else if( item->base == NULL )
3107         {
3108                 rtexture_t *dyntexture;
3109                 // check whether its a dynamic texture
3110                 // 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]
3111                 dyntexture = CL_GetDynTexture( basename );
3112                 item->base = dyntexture; // either NULL or dyntexture handle
3113         }
3114
3115         R_SkinFrame_MarkUsed(item);
3116         return item;
3117 }
3118
3119 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3120         { \
3121                 unsigned long long avgcolor[5], wsum; \
3122                 int pix, comp, w; \
3123                 avgcolor[0] = 0; \
3124                 avgcolor[1] = 0; \
3125                 avgcolor[2] = 0; \
3126                 avgcolor[3] = 0; \
3127                 avgcolor[4] = 0; \
3128                 wsum = 0; \
3129                 for(pix = 0; pix < cnt; ++pix) \
3130                 { \
3131                         w = 0; \
3132                         for(comp = 0; comp < 3; ++comp) \
3133                                 w += getpixel; \
3134                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3135                         { \
3136                                 ++wsum; \
3137                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3138                                 w = getpixel; \
3139                                 for(comp = 0; comp < 3; ++comp) \
3140                                         avgcolor[comp] += getpixel * w; \
3141                                 avgcolor[3] += w; \
3142                         } \
3143                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3144                         avgcolor[4] += getpixel; \
3145                 } \
3146                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3147                         avgcolor[3] = 1; \
3148                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3149                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3150                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3151                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3152         }
3153
3154 extern cvar_t gl_picmip;
3155 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3156 {
3157         int j;
3158         unsigned char *pixels;
3159         unsigned char *bumppixels;
3160         unsigned char *basepixels = NULL;
3161         int basepixels_width = 0;
3162         int basepixels_height = 0;
3163         skinframe_t *skinframe;
3164         rtexture_t *ddsbase = NULL;
3165         qboolean ddshasalpha = false;
3166         float ddsavgcolor[4];
3167         char basename[MAX_QPATH];
3168         int miplevel = R_PicmipForFlags(textureflags);
3169         int savemiplevel = miplevel;
3170         int mymiplevel;
3171
3172         if (cls.state == ca_dedicated)
3173                 return NULL;
3174
3175         // return an existing skinframe if already loaded
3176         // if loading of the first image fails, don't make a new skinframe as it
3177         // would cause all future lookups of this to be missing
3178         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3179         if (skinframe && skinframe->base)
3180                 return skinframe;
3181
3182         Image_StripImageExtension(name, basename, sizeof(basename));
3183
3184         // check for DDS texture file first
3185         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3186         {
3187                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3188                 if (basepixels == NULL)
3189                         return NULL;
3190         }
3191
3192         // FIXME handle miplevel
3193
3194         if (developer_loading.integer)
3195                 Con_Printf("loading skin \"%s\"\n", name);
3196
3197         // we've got some pixels to store, so really allocate this new texture now
3198         if (!skinframe)
3199                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3200         skinframe->stain = NULL;
3201         skinframe->merged = NULL;
3202         skinframe->base = NULL;
3203         skinframe->pants = NULL;
3204         skinframe->shirt = NULL;
3205         skinframe->nmap = NULL;
3206         skinframe->gloss = NULL;
3207         skinframe->glow = NULL;
3208         skinframe->fog = NULL;
3209         skinframe->reflect = NULL;
3210         skinframe->hasalpha = false;
3211
3212         if (ddsbase)
3213         {
3214                 skinframe->base = ddsbase;
3215                 skinframe->hasalpha = ddshasalpha;
3216                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3217                 if (r_loadfog && skinframe->hasalpha)
3218                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3219                 //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]);
3220         }
3221         else
3222         {
3223                 basepixels_width = image_width;
3224                 basepixels_height = image_height;
3225                 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);
3226                 if (textureflags & TEXF_ALPHA)
3227                 {
3228                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3229                         {
3230                                 if (basepixels[j] < 255)
3231                                 {
3232                                         skinframe->hasalpha = true;
3233                                         break;
3234                                 }
3235                         }
3236                         if (r_loadfog && skinframe->hasalpha)
3237                         {
3238                                 // has transparent pixels
3239                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3240                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3241                                 {
3242                                         pixels[j+0] = 255;
3243                                         pixels[j+1] = 255;
3244                                         pixels[j+2] = 255;
3245                                         pixels[j+3] = basepixels[j+3];
3246                                 }
3247                                 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);
3248                                 Mem_Free(pixels);
3249                         }
3250                 }
3251                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3252                 //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]);
3253                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3254                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3255                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3256                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3257         }
3258
3259         if (r_loaddds)
3260         {
3261                 mymiplevel = savemiplevel;
3262                 if (r_loadnormalmap)
3263                         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);
3264                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3265                 if (r_loadgloss)
3266                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3267                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3268                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3269                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3270         }
3271
3272         // _norm is the name used by tenebrae and has been adopted as standard
3273         if (r_loadnormalmap && skinframe->nmap == NULL)
3274         {
3275                 mymiplevel = savemiplevel;
3276                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3277                 {
3278                         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);
3279                         Mem_Free(pixels);
3280                         pixels = NULL;
3281                 }
3282                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3283                 {
3284                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3285                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3286                         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);
3287                         Mem_Free(pixels);
3288                         Mem_Free(bumppixels);
3289                 }
3290                 else if (r_shadow_bumpscale_basetexture.value > 0)
3291                 {
3292                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3293                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3294                         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);
3295                         Mem_Free(pixels);
3296                 }
3297                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3298                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3299         }
3300
3301         // _luma is supported only for tenebrae compatibility
3302         // _glow is the preferred name
3303         mymiplevel = savemiplevel;
3304         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))))
3305         {
3306                 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);
3307                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3308                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3309                 Mem_Free(pixels);pixels = NULL;
3310         }
3311
3312         mymiplevel = savemiplevel;
3313         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3314         {
3315                 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);
3316                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3317                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3318                 Mem_Free(pixels);
3319                 pixels = NULL;
3320         }
3321
3322         mymiplevel = savemiplevel;
3323         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3324         {
3325                 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);
3326                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3327                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3328                 Mem_Free(pixels);
3329                 pixels = NULL;
3330         }
3331
3332         mymiplevel = savemiplevel;
3333         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3334         {
3335                 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);
3336                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3337                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3338                 Mem_Free(pixels);
3339                 pixels = NULL;
3340         }
3341
3342         mymiplevel = savemiplevel;
3343         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3344         {
3345                 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);
3346                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3347                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3348                 Mem_Free(pixels);
3349                 pixels = NULL;
3350         }
3351
3352         if (basepixels)
3353                 Mem_Free(basepixels);
3354
3355         return skinframe;
3356 }
3357
3358 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3359 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3360 {
3361         int i;
3362         unsigned char *temp1, *temp2;
3363         skinframe_t *skinframe;
3364
3365         if (cls.state == ca_dedicated)
3366                 return NULL;
3367
3368         // if already loaded just return it, otherwise make a new skinframe
3369         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3370         if (skinframe && skinframe->base)
3371                 return skinframe;
3372
3373         skinframe->stain = NULL;
3374         skinframe->merged = NULL;
3375         skinframe->base = NULL;
3376         skinframe->pants = NULL;
3377         skinframe->shirt = NULL;
3378         skinframe->nmap = NULL;
3379         skinframe->gloss = NULL;
3380         skinframe->glow = NULL;
3381         skinframe->fog = NULL;
3382         skinframe->reflect = NULL;
3383         skinframe->hasalpha = false;
3384
3385         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3386         if (!skindata)
3387                 return NULL;
3388
3389         if (developer_loading.integer)
3390                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3391
3392         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3393         {
3394                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3395                 temp2 = temp1 + width * height * 4;
3396                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3397                 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);
3398                 Mem_Free(temp1);
3399         }
3400         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3401         if (textureflags & TEXF_ALPHA)
3402         {
3403                 for (i = 3;i < width * height * 4;i += 4)
3404                 {
3405                         if (skindata[i] < 255)
3406                         {
3407                                 skinframe->hasalpha = true;
3408                                 break;
3409                         }
3410                 }
3411                 if (r_loadfog && skinframe->hasalpha)
3412                 {
3413                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3414                         memcpy(fogpixels, skindata, width * height * 4);
3415                         for (i = 0;i < width * height * 4;i += 4)
3416                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3417                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3418                         Mem_Free(fogpixels);
3419                 }
3420         }
3421
3422         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3423         //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]);
3424
3425         return skinframe;
3426 }
3427
3428 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3429 {
3430         int i;
3431         int featuresmask;
3432         skinframe_t *skinframe;
3433
3434         if (cls.state == ca_dedicated)
3435                 return NULL;
3436
3437         // if already loaded just return it, otherwise make a new skinframe
3438         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3439         if (skinframe && skinframe->base)
3440                 return skinframe;
3441
3442         skinframe->stain = NULL;
3443         skinframe->merged = NULL;
3444         skinframe->base = NULL;
3445         skinframe->pants = NULL;
3446         skinframe->shirt = NULL;
3447         skinframe->nmap = NULL;
3448         skinframe->gloss = NULL;
3449         skinframe->glow = NULL;
3450         skinframe->fog = NULL;
3451         skinframe->reflect = NULL;
3452         skinframe->hasalpha = false;
3453
3454         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3455         if (!skindata)
3456                 return NULL;
3457
3458         if (developer_loading.integer)
3459                 Con_Printf("loading quake skin \"%s\"\n", name);
3460
3461         // 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)
3462         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3463         memcpy(skinframe->qpixels, skindata, width*height);
3464         skinframe->qwidth = width;
3465         skinframe->qheight = height;
3466
3467         featuresmask = 0;
3468         for (i = 0;i < width * height;i++)
3469                 featuresmask |= palette_featureflags[skindata[i]];
3470
3471         skinframe->hasalpha = false;
3472         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3473         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3474         skinframe->qgeneratemerged = true;
3475         skinframe->qgeneratebase = skinframe->qhascolormapping;
3476         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3477
3478         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3479         //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]);
3480
3481         return skinframe;
3482 }
3483
3484 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3485 {
3486         int width;
3487         int height;
3488         unsigned char *skindata;
3489
3490         if (!skinframe->qpixels)
3491                 return;
3492
3493         if (!skinframe->qhascolormapping)
3494                 colormapped = false;
3495
3496         if (colormapped)
3497         {
3498                 if (!skinframe->qgeneratebase)
3499                         return;
3500         }
3501         else
3502         {
3503                 if (!skinframe->qgeneratemerged)
3504                         return;
3505         }
3506
3507         width = skinframe->qwidth;
3508         height = skinframe->qheight;
3509         skindata = skinframe->qpixels;
3510
3511         if (skinframe->qgeneratenmap)
3512         {
3513                 unsigned char *temp1, *temp2;
3514                 skinframe->qgeneratenmap = false;
3515                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3516                 temp2 = temp1 + width * height * 4;
3517                 // use either a custom palette or the quake palette
3518                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3519                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3520                 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);
3521                 Mem_Free(temp1);
3522         }
3523
3524         if (skinframe->qgenerateglow)
3525         {
3526                 skinframe->qgenerateglow = false;
3527                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3528         }
3529
3530         if (colormapped)
3531         {
3532                 skinframe->qgeneratebase = false;
3533                 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);
3534                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3535                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3536         }
3537         else
3538         {
3539                 skinframe->qgeneratemerged = false;
3540                 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);
3541         }
3542
3543         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3544         {
3545                 Mem_Free(skinframe->qpixels);
3546                 skinframe->qpixels = NULL;
3547         }
3548 }
3549
3550 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)
3551 {
3552         int i;
3553         skinframe_t *skinframe;
3554
3555         if (cls.state == ca_dedicated)
3556                 return NULL;
3557
3558         // if already loaded just return it, otherwise make a new skinframe
3559         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3560         if (skinframe && skinframe->base)
3561                 return skinframe;
3562
3563         skinframe->stain = NULL;
3564         skinframe->merged = NULL;
3565         skinframe->base = NULL;
3566         skinframe->pants = NULL;
3567         skinframe->shirt = NULL;
3568         skinframe->nmap = NULL;
3569         skinframe->gloss = NULL;
3570         skinframe->glow = NULL;
3571         skinframe->fog = NULL;
3572         skinframe->reflect = NULL;
3573         skinframe->hasalpha = false;
3574
3575         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3576         if (!skindata)
3577                 return NULL;
3578
3579         if (developer_loading.integer)
3580                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3581
3582         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3583         if (textureflags & TEXF_ALPHA)
3584         {
3585                 for (i = 0;i < width * height;i++)
3586                 {
3587                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3588                         {
3589                                 skinframe->hasalpha = true;
3590                                 break;
3591                         }
3592                 }
3593                 if (r_loadfog && skinframe->hasalpha)
3594                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3595         }
3596
3597         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3598         //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]);
3599
3600         return skinframe;
3601 }
3602
3603 skinframe_t *R_SkinFrame_LoadMissing(void)
3604 {
3605         skinframe_t *skinframe;
3606
3607         if (cls.state == ca_dedicated)
3608                 return NULL;
3609
3610         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3611         skinframe->stain = NULL;
3612         skinframe->merged = NULL;
3613         skinframe->base = NULL;
3614         skinframe->pants = NULL;
3615         skinframe->shirt = NULL;
3616         skinframe->nmap = NULL;
3617         skinframe->gloss = NULL;
3618         skinframe->glow = NULL;
3619         skinframe->fog = NULL;
3620         skinframe->reflect = NULL;
3621         skinframe->hasalpha = false;
3622
3623         skinframe->avgcolor[0] = rand() / RAND_MAX;
3624         skinframe->avgcolor[1] = rand() / RAND_MAX;
3625         skinframe->avgcolor[2] = rand() / RAND_MAX;
3626         skinframe->avgcolor[3] = 1;
3627
3628         return skinframe;
3629 }
3630
3631 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3632 typedef struct suffixinfo_s
3633 {
3634         const char *suffix;
3635         qboolean flipx, flipy, flipdiagonal;
3636 }
3637 suffixinfo_t;
3638 static suffixinfo_t suffix[3][6] =
3639 {
3640         {
3641                 {"px",   false, false, false},
3642                 {"nx",   false, false, false},
3643                 {"py",   false, false, false},
3644                 {"ny",   false, false, false},
3645                 {"pz",   false, false, false},
3646                 {"nz",   false, false, false}
3647         },
3648         {
3649                 {"posx", false, false, false},
3650                 {"negx", false, false, false},
3651                 {"posy", false, false, false},
3652                 {"negy", false, false, false},
3653                 {"posz", false, false, false},
3654                 {"negz", false, false, false}
3655         },
3656         {
3657                 {"rt",    true, false,  true},
3658                 {"lf",   false,  true,  true},
3659                 {"ft",    true,  true, false},
3660                 {"bk",   false, false, false},
3661                 {"up",    true, false,  true},
3662                 {"dn",    true, false,  true}
3663         }
3664 };
3665
3666 static int componentorder[4] = {0, 1, 2, 3};
3667
3668 rtexture_t *R_LoadCubemap(const char *basename)
3669 {
3670         int i, j, cubemapsize;
3671         unsigned char *cubemappixels, *image_buffer;
3672         rtexture_t *cubemaptexture;
3673         char name[256];
3674         // must start 0 so the first loadimagepixels has no requested width/height
3675         cubemapsize = 0;
3676         cubemappixels = NULL;
3677         cubemaptexture = NULL;
3678         // keep trying different suffix groups (posx, px, rt) until one loads
3679         for (j = 0;j < 3 && !cubemappixels;j++)
3680         {
3681                 // load the 6 images in the suffix group
3682                 for (i = 0;i < 6;i++)
3683                 {
3684                         // generate an image name based on the base and and suffix
3685                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3686                         // load it
3687                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3688                         {
3689                                 // an image loaded, make sure width and height are equal
3690                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3691                                 {
3692                                         // if this is the first image to load successfully, allocate the cubemap memory
3693                                         if (!cubemappixels && image_width >= 1)
3694                                         {
3695                                                 cubemapsize = image_width;
3696                                                 // note this clears to black, so unavailable sides are black
3697                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3698                                         }
3699                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3700                                         if (cubemappixels)
3701                                                 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);
3702                                 }
3703                                 else
3704                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3705                                 // free the image
3706                                 Mem_Free(image_buffer);
3707                         }
3708                 }
3709         }
3710         // if a cubemap loaded, upload it
3711         if (cubemappixels)
3712         {
3713                 if (developer_loading.integer)
3714                         Con_Printf("loading cubemap \"%s\"\n", basename);
3715
3716                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3717                 Mem_Free(cubemappixels);
3718         }
3719         else
3720         {
3721                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3722                 if (developer_loading.integer)
3723                 {
3724                         Con_Printf("(tried tried images ");
3725                         for (j = 0;j < 3;j++)
3726                                 for (i = 0;i < 6;i++)
3727                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3728                         Con_Print(" and was unable to find any of them).\n");
3729                 }
3730         }
3731         return cubemaptexture;
3732 }
3733
3734 rtexture_t *R_GetCubemap(const char *basename)
3735 {
3736         int i;
3737         for (i = 0;i < r_texture_numcubemaps;i++)
3738                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3739                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3740         if (i >= MAX_CUBEMAPS)
3741                 return r_texture_whitecube;
3742         r_texture_numcubemaps++;
3743         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3744         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3745         return r_texture_cubemaps[i].texture;
3746 }
3747
3748 void R_FreeCubemaps(void)
3749 {
3750         int i;
3751         for (i = 0;i < r_texture_numcubemaps;i++)
3752         {
3753                 if (developer_loading.integer)
3754                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3755                 if (r_texture_cubemaps[i].texture)
3756                         R_FreeTexture(r_texture_cubemaps[i].texture);
3757         }
3758         r_texture_numcubemaps = 0;
3759 }
3760
3761 void R_Main_FreeViewCache(void)
3762 {
3763         if (r_refdef.viewcache.entityvisible)
3764                 Mem_Free(r_refdef.viewcache.entityvisible);
3765         if (r_refdef.viewcache.world_pvsbits)
3766                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3767         if (r_refdef.viewcache.world_leafvisible)
3768                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3769         if (r_refdef.viewcache.world_surfacevisible)
3770                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3771         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3772 }
3773
3774 void R_Main_ResizeViewCache(void)
3775 {
3776         int numentities = r_refdef.scene.numentities;
3777         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3778         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3779         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3780         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3781         if (r_refdef.viewcache.maxentities < numentities)
3782         {
3783                 r_refdef.viewcache.maxentities = numentities;
3784                 if (r_refdef.viewcache.entityvisible)
3785                         Mem_Free(r_refdef.viewcache.entityvisible);
3786                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3787         }
3788         if (r_refdef.viewcache.world_numclusters != numclusters)
3789         {
3790                 r_refdef.viewcache.world_numclusters = numclusters;
3791                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3792                 if (r_refdef.viewcache.world_pvsbits)
3793                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3794                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3795         }
3796         if (r_refdef.viewcache.world_numleafs != numleafs)
3797         {
3798                 r_refdef.viewcache.world_numleafs = numleafs;
3799                 if (r_refdef.viewcache.world_leafvisible)
3800                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3801                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3802         }
3803         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3804         {
3805                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3806                 if (r_refdef.viewcache.world_surfacevisible)
3807                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3808                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3809         }
3810 }
3811
3812 extern rtexture_t *loadingscreentexture;
3813 void gl_main_start(void)
3814 {
3815         loadingscreentexture = NULL;
3816         r_texture_blanknormalmap = NULL;
3817         r_texture_white = NULL;
3818         r_texture_grey128 = NULL;
3819         r_texture_black = NULL;
3820         r_texture_whitecube = NULL;
3821         r_texture_normalizationcube = NULL;
3822         r_texture_fogattenuation = NULL;
3823         r_texture_fogheighttexture = NULL;
3824         r_texture_gammaramps = NULL;
3825         r_texture_numcubemaps = 0;
3826
3827         r_loaddds = r_texture_dds_load.integer != 0;
3828         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3829
3830         switch(vid.renderpath)
3831         {
3832         case RENDERPATH_GL20:
3833         case RENDERPATH_D3D9:
3834         case RENDERPATH_D3D10:
3835         case RENDERPATH_D3D11:
3836         case RENDERPATH_SOFT:
3837                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3838                 Cvar_SetValueQuick(&gl_combine, 1);
3839                 Cvar_SetValueQuick(&r_glsl, 1);
3840                 r_loadnormalmap = true;
3841                 r_loadgloss = true;
3842                 r_loadfog = false;
3843                 break;
3844         case RENDERPATH_GL13:
3845                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3846                 Cvar_SetValueQuick(&gl_combine, 1);
3847                 Cvar_SetValueQuick(&r_glsl, 0);
3848                 r_loadnormalmap = false;
3849                 r_loadgloss = false;
3850                 r_loadfog = true;
3851                 break;
3852         case RENDERPATH_GL11:
3853                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3854                 Cvar_SetValueQuick(&gl_combine, 0);
3855                 Cvar_SetValueQuick(&r_glsl, 0);
3856                 r_loadnormalmap = false;
3857                 r_loadgloss = false;
3858                 r_loadfog = true;
3859                 break;
3860         case RENDERPATH_GLES2:
3861                 Cvar_SetValueQuick(&r_textureunits, 1);
3862                 Cvar_SetValueQuick(&gl_combine, 1);
3863                 Cvar_SetValueQuick(&r_glsl, 1);
3864                 r_loadnormalmap = true;
3865                 r_loadgloss = false;
3866                 r_loadfog = false;
3867                 break;
3868         }
3869
3870         R_AnimCache_Free();
3871         R_FrameData_Reset();
3872
3873         r_numqueries = 0;
3874         r_maxqueries = 0;
3875         memset(r_queries, 0, sizeof(r_queries));
3876
3877         r_qwskincache = NULL;
3878         r_qwskincache_size = 0;
3879
3880         // due to caching of texture_t references, the collision cache must be reset
3881         Collision_Cache_Reset(true);
3882
3883         // set up r_skinframe loading system for textures
3884         memset(&r_skinframe, 0, sizeof(r_skinframe));
3885         r_skinframe.loadsequence = 1;
3886         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3887
3888         r_main_texturepool = R_AllocTexturePool();
3889         R_BuildBlankTextures();
3890         R_BuildNoTexture();
3891         if (vid.support.arb_texture_cube_map)
3892         {
3893                 R_BuildWhiteCube();
3894                 R_BuildNormalizationCube();
3895         }
3896         r_texture_fogattenuation = NULL;
3897         r_texture_fogheighttexture = NULL;
3898         r_texture_gammaramps = NULL;
3899         //r_texture_fogintensity = NULL;
3900         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3901         memset(&r_waterstate, 0, sizeof(r_waterstate));
3902         r_glsl_permutation = NULL;
3903         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3904         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3905         glslshaderstring = NULL;
3906 #ifdef SUPPORTD3D
3907         r_hlsl_permutation = NULL;
3908         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3909         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3910 #endif
3911         hlslshaderstring = NULL;
3912         memset(&r_svbsp, 0, sizeof (r_svbsp));
3913
3914         r_refdef.fogmasktable_density = 0;
3915 }
3916
3917 void gl_main_shutdown(void)
3918 {
3919         R_AnimCache_Free();
3920         R_FrameData_Reset();
3921
3922         R_Main_FreeViewCache();
3923
3924         switch(vid.renderpath)
3925         {
3926         case RENDERPATH_GL11:
3927         case RENDERPATH_GL13:
3928         case RENDERPATH_GL20:
3929         case RENDERPATH_GLES2:
3930                 if (r_maxqueries)
3931                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3932                 break;
3933         case RENDERPATH_D3D9:
3934                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3935                 break;
3936         case RENDERPATH_D3D10:
3937                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3938                 break;
3939         case RENDERPATH_D3D11:
3940                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3941                 break;
3942         case RENDERPATH_SOFT:
3943                 break;
3944         }
3945
3946         r_numqueries = 0;
3947         r_maxqueries = 0;
3948         memset(r_queries, 0, sizeof(r_queries));
3949
3950         r_qwskincache = NULL;
3951         r_qwskincache_size = 0;
3952
3953         // clear out the r_skinframe state
3954         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3955         memset(&r_skinframe, 0, sizeof(r_skinframe));
3956
3957         if (r_svbsp.nodes)
3958                 Mem_Free(r_svbsp.nodes);
3959         memset(&r_svbsp, 0, sizeof (r_svbsp));
3960         R_FreeTexturePool(&r_main_texturepool);
3961         loadingscreentexture = NULL;
3962         r_texture_blanknormalmap = NULL;
3963         r_texture_white = NULL;
3964         r_texture_grey128 = NULL;
3965         r_texture_black = NULL;
3966         r_texture_whitecube = NULL;
3967         r_texture_normalizationcube = NULL;
3968         r_texture_fogattenuation = NULL;
3969         r_texture_fogheighttexture = NULL;
3970         r_texture_gammaramps = NULL;
3971         r_texture_numcubemaps = 0;
3972         //r_texture_fogintensity = NULL;
3973         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3974         memset(&r_waterstate, 0, sizeof(r_waterstate));
3975         R_GLSL_Restart_f();
3976
3977         r_glsl_permutation = NULL;
3978         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3979         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3980         glslshaderstring = NULL;
3981 #ifdef SUPPORTD3D
3982         r_hlsl_permutation = NULL;
3983         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3984         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3985 #endif
3986         hlslshaderstring = NULL;
3987 }
3988
3989 extern void CL_ParseEntityLump(char *entitystring);
3990 void gl_main_newmap(void)
3991 {
3992         // FIXME: move this code to client
3993         char *entities, entname[MAX_QPATH];
3994         if (r_qwskincache)
3995                 Mem_Free(r_qwskincache);
3996         r_qwskincache = NULL;
3997         r_qwskincache_size = 0;
3998         if (cl.worldmodel)
3999         {
4000                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4001                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4002                 {
4003                         CL_ParseEntityLump(entities);
4004                         Mem_Free(entities);
4005                         return;
4006                 }
4007                 if (cl.worldmodel->brush.entities)
4008                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4009         }
4010         R_Main_FreeViewCache();
4011
4012         R_FrameData_Reset();
4013 }
4014
4015 void GL_Main_Init(void)
4016 {
4017         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4018
4019         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4020         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4021         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4022         if (gamemode == GAME_NEHAHRA)
4023         {
4024                 Cvar_RegisterVariable (&gl_fogenable);
4025                 Cvar_RegisterVariable (&gl_fogdensity);
4026                 Cvar_RegisterVariable (&gl_fogred);
4027                 Cvar_RegisterVariable (&gl_foggreen);
4028                 Cvar_RegisterVariable (&gl_fogblue);
4029                 Cvar_RegisterVariable (&gl_fogstart);
4030                 Cvar_RegisterVariable (&gl_fogend);
4031                 Cvar_RegisterVariable (&gl_skyclip);
4032         }
4033         Cvar_RegisterVariable(&r_motionblur);
4034         Cvar_RegisterVariable(&r_motionblur_maxblur);
4035         Cvar_RegisterVariable(&r_motionblur_bmin);
4036         Cvar_RegisterVariable(&r_motionblur_vmin);
4037         Cvar_RegisterVariable(&r_motionblur_vmax);
4038         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4039         Cvar_RegisterVariable(&r_motionblur_randomize);
4040         Cvar_RegisterVariable(&r_damageblur);
4041         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4042         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4043         Cvar_RegisterVariable(&r_equalize_entities_by);
4044         Cvar_RegisterVariable(&r_equalize_entities_to);
4045         Cvar_RegisterVariable(&r_depthfirst);
4046         Cvar_RegisterVariable(&r_useinfinitefarclip);
4047         Cvar_RegisterVariable(&r_farclip_base);
4048         Cvar_RegisterVariable(&r_farclip_world);
4049         Cvar_RegisterVariable(&r_nearclip);
4050         Cvar_RegisterVariable(&r_showbboxes);
4051         Cvar_RegisterVariable(&r_showsurfaces);
4052         Cvar_RegisterVariable(&r_showtris);
4053         Cvar_RegisterVariable(&r_shownormals);
4054         Cvar_RegisterVariable(&r_showlighting);
4055         Cvar_RegisterVariable(&r_showshadowvolumes);
4056         Cvar_RegisterVariable(&r_showcollisionbrushes);
4057         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4058         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4059         Cvar_RegisterVariable(&r_showdisabledepthtest);
4060         Cvar_RegisterVariable(&r_drawportals);
4061         Cvar_RegisterVariable(&r_drawentities);
4062         Cvar_RegisterVariable(&r_draw2d);
4063         Cvar_RegisterVariable(&r_drawworld);
4064         Cvar_RegisterVariable(&r_cullentities_trace);
4065         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4066         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4067         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4068         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4069         Cvar_RegisterVariable(&r_drawviewmodel);
4070         Cvar_RegisterVariable(&r_drawexteriormodel);
4071         Cvar_RegisterVariable(&r_speeds);
4072         Cvar_RegisterVariable(&r_fullbrights);
4073         Cvar_RegisterVariable(&r_wateralpha);
4074         Cvar_RegisterVariable(&r_dynamic);
4075         Cvar_RegisterVariable(&r_fakelight);
4076         Cvar_RegisterVariable(&r_fakelight_intensity);
4077         Cvar_RegisterVariable(&r_fullbright);
4078         Cvar_RegisterVariable(&r_shadows);
4079         Cvar_RegisterVariable(&r_shadows_darken);
4080         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4081         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4082         Cvar_RegisterVariable(&r_shadows_throwdistance);
4083         Cvar_RegisterVariable(&r_shadows_throwdirection);
4084         Cvar_RegisterVariable(&r_shadows_focus);
4085         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4086         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4087         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4088         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4089         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4090         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4091         Cvar_RegisterVariable(&r_fog_exp2);
4092         Cvar_RegisterVariable(&r_fog_clear);
4093         Cvar_RegisterVariable(&r_drawfog);
4094         Cvar_RegisterVariable(&r_transparentdepthmasking);
4095         Cvar_RegisterVariable(&r_texture_dds_load);
4096         Cvar_RegisterVariable(&r_texture_dds_save);
4097         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4098         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4099         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4100         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4101         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4102         Cvar_RegisterVariable(&r_textureunits);
4103         Cvar_RegisterVariable(&gl_combine);
4104         Cvar_RegisterVariable(&r_viewfbo);
4105         Cvar_RegisterVariable(&r_viewscale);
4106         Cvar_RegisterVariable(&r_glsl);
4107         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4108         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4109         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4110         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4111         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4112         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4113         Cvar_RegisterVariable(&r_glsl_postprocess);
4114         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4115         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4116         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4117         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4118         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4119         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4120         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4121         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4122
4123         Cvar_RegisterVariable(&r_water);
4124         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4125         Cvar_RegisterVariable(&r_water_clippingplanebias);
4126         Cvar_RegisterVariable(&r_water_refractdistort);
4127         Cvar_RegisterVariable(&r_water_reflectdistort);
4128         Cvar_RegisterVariable(&r_water_scissormode);
4129         Cvar_RegisterVariable(&r_lerpsprites);
4130         Cvar_RegisterVariable(&r_lerpmodels);
4131         Cvar_RegisterVariable(&r_lerplightstyles);
4132         Cvar_RegisterVariable(&r_waterscroll);
4133         Cvar_RegisterVariable(&r_bloom);
4134         Cvar_RegisterVariable(&r_bloom_colorscale);
4135         Cvar_RegisterVariable(&r_bloom_brighten);
4136         Cvar_RegisterVariable(&r_bloom_blur);
4137         Cvar_RegisterVariable(&r_bloom_resolution);
4138         Cvar_RegisterVariable(&r_bloom_colorexponent);
4139         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4140         Cvar_RegisterVariable(&r_hdr);
4141         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4142         Cvar_RegisterVariable(&r_hdr_glowintensity);
4143         Cvar_RegisterVariable(&r_hdr_range);
4144         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4145         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4146         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4147         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4148         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4149         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4150         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4151         Cvar_RegisterVariable(&developer_texturelogging);
4152         Cvar_RegisterVariable(&gl_lightmaps);
4153         Cvar_RegisterVariable(&r_test);
4154         Cvar_RegisterVariable(&r_glsl_saturation);
4155         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4156         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4157         Cvar_RegisterVariable(&r_framedatasize);
4158         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4159                 Cvar_SetValue("r_fullbrights", 0);
4160         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4161
4162         Cvar_RegisterVariable(&r_track_sprites);
4163         Cvar_RegisterVariable(&r_track_sprites_flags);
4164         Cvar_RegisterVariable(&r_track_sprites_scalew);
4165         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4166         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4167         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4168         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4169         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4170 }
4171
4172 extern void R_Textures_Init(void);
4173 extern void GL_Draw_Init(void);
4174 extern void GL_Main_Init(void);
4175 extern void R_Shadow_Init(void);
4176 extern void R_Sky_Init(void);
4177 extern void GL_Surf_Init(void);
4178 extern void R_Particles_Init(void);
4179 extern void R_Explosion_Init(void);
4180 extern void gl_backend_init(void);
4181 extern void Sbar_Init(void);
4182 extern void R_LightningBeams_Init(void);
4183 extern void Mod_RenderInit(void);
4184 extern void Font_Init(void);
4185
4186 void Render_Init(void)
4187 {
4188         gl_backend_init();
4189         R_Textures_Init();
4190         GL_Main_Init();
4191         Font_Init();
4192         GL_Draw_Init();
4193         R_Shadow_Init();
4194         R_Sky_Init();
4195         GL_Surf_Init();
4196         Sbar_Init();
4197         R_Particles_Init();
4198         R_Explosion_Init();
4199         R_LightningBeams_Init();
4200         Mod_RenderInit();
4201 }
4202
4203 /*
4204 ===============
4205 GL_Init
4206 ===============
4207 */
4208 extern char *ENGINE_EXTENSIONS;
4209 void GL_Init (void)
4210 {
4211         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4212         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4213         gl_version = (const char *)qglGetString(GL_VERSION);
4214         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4215
4216         if (!gl_extensions)
4217                 gl_extensions = "";
4218         if (!gl_platformextensions)
4219                 gl_platformextensions = "";
4220
4221         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4222         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4223         Con_Printf("GL_VERSION: %s\n", gl_version);
4224         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4225         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4226
4227         VID_CheckExtensions();
4228
4229         // LordHavoc: report supported extensions
4230         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4231
4232         // clear to black (loading plaque will be seen over this)
4233         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4234 }
4235
4236 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4237 {
4238         int i;
4239         mplane_t *p;
4240         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4241         {
4242                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4243                 if (i == 4)
4244                         continue;
4245                 p = r_refdef.view.frustum + i;
4246                 switch(p->signbits)
4247                 {
4248                 default:
4249                 case 0:
4250                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4251                                 return true;
4252                         break;
4253                 case 1:
4254                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4255                                 return true;
4256                         break;
4257                 case 2:
4258                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4259                                 return true;
4260                         break;
4261                 case 3:
4262                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4263                                 return true;
4264                         break;
4265                 case 4:
4266                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4267                                 return true;
4268                         break;
4269                 case 5:
4270                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4271                                 return true;
4272                         break;
4273                 case 6:
4274                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4275                                 return true;
4276                         break;
4277                 case 7:
4278                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4279                                 return true;
4280                         break;
4281                 }
4282         }
4283         return false;
4284 }
4285
4286 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4287 {
4288         int i;
4289         const mplane_t *p;
4290         for (i = 0;i < numplanes;i++)
4291         {
4292                 p = planes + i;
4293                 switch(p->signbits)
4294                 {
4295                 default:
4296                 case 0:
4297                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4298                                 return true;
4299                         break;
4300                 case 1:
4301                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4302                                 return true;
4303                         break;
4304                 case 2:
4305                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4306                                 return true;
4307                         break;
4308                 case 3:
4309                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4310                                 return true;
4311                         break;
4312                 case 4:
4313                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4314                                 return true;
4315                         break;
4316                 case 5:
4317                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4318                                 return true;
4319                         break;
4320                 case 6:
4321                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4322                                 return true;
4323                         break;
4324                 case 7:
4325                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4326                                 return true;
4327                         break;
4328                 }
4329         }
4330         return false;
4331 }
4332
4333 //==================================================================================
4334
4335 // LordHavoc: this stores temporary data used within the same frame
4336
4337 typedef struct r_framedata_mem_s
4338 {
4339         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4340         size_t size; // how much usable space
4341         size_t current; // how much space in use
4342         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4343         size_t wantedsize; // how much space was allocated
4344         unsigned char *data; // start of real data (16byte aligned)
4345 }
4346 r_framedata_mem_t;
4347
4348 static r_framedata_mem_t *r_framedata_mem;
4349
4350 void R_FrameData_Reset(void)
4351 {
4352         while (r_framedata_mem)
4353         {
4354                 r_framedata_mem_t *next = r_framedata_mem->purge;
4355                 Mem_Free(r_framedata_mem);
4356                 r_framedata_mem = next;
4357         }
4358 }
4359
4360 void R_FrameData_Resize(void)
4361 {
4362         size_t wantedsize;
4363         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4364         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4365         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4366         {
4367                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4368                 newmem->wantedsize = wantedsize;
4369                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4370                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4371                 newmem->current = 0;
4372                 newmem->mark = 0;
4373                 newmem->purge = r_framedata_mem;
4374                 r_framedata_mem = newmem;
4375         }
4376 }
4377
4378 void R_FrameData_NewFrame(void)
4379 {
4380         R_FrameData_Resize();
4381         if (!r_framedata_mem)
4382                 return;
4383         // if we ran out of space on the last frame, free the old memory now
4384         while (r_framedata_mem->purge)
4385         {
4386                 // repeatedly remove the second item in the list, leaving only head
4387                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4388                 Mem_Free(r_framedata_mem->purge);
4389                 r_framedata_mem->purge = next;
4390         }
4391         // reset the current mem pointer
4392         r_framedata_mem->current = 0;
4393         r_framedata_mem->mark = 0;
4394 }
4395
4396 void *R_FrameData_Alloc(size_t size)
4397 {
4398         void *data;
4399
4400         // align to 16 byte boundary - the data pointer is already aligned, so we
4401         // only need to ensure the size of every allocation is also aligned
4402         size = (size + 15) & ~15;
4403
4404         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4405         {
4406                 // emergency - we ran out of space, allocate more memory
4407                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4408                 R_FrameData_Resize();
4409         }
4410
4411         data = r_framedata_mem->data + r_framedata_mem->current;
4412         r_framedata_mem->current += size;
4413
4414         // count the usage for stats
4415         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4416         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4417
4418         return (void *)data;
4419 }
4420
4421 void *R_FrameData_Store(size_t size, void *data)
4422 {
4423         void *d = R_FrameData_Alloc(size);
4424         if (d && data)
4425                 memcpy(d, data, size);
4426         return d;
4427 }
4428
4429 void R_FrameData_SetMark(void)
4430 {
4431         if (!r_framedata_mem)
4432                 return;
4433         r_framedata_mem->mark = r_framedata_mem->current;
4434 }
4435
4436 void R_FrameData_ReturnToMark(void)
4437 {
4438         if (!r_framedata_mem)
4439                 return;
4440         r_framedata_mem->current = r_framedata_mem->mark;
4441 }
4442
4443 //==================================================================================
4444
4445 // LordHavoc: animcache originally written by Echon, rewritten since then
4446
4447 /**
4448  * Animation cache prevents re-generating mesh data for an animated model
4449  * multiple times in one frame for lighting, shadowing, reflections, etc.
4450  */
4451
4452 void R_AnimCache_Free(void)
4453 {
4454 }
4455
4456 void R_AnimCache_ClearCache(void)
4457 {
4458         int i;
4459         entity_render_t *ent;
4460
4461         for (i = 0;i < r_refdef.scene.numentities;i++)
4462         {
4463                 ent = r_refdef.scene.entities[i];
4464                 ent->animcache_vertex3f = NULL;
4465                 ent->animcache_normal3f = NULL;
4466                 ent->animcache_svector3f = NULL;
4467                 ent->animcache_tvector3f = NULL;
4468                 ent->animcache_vertexmesh = NULL;
4469                 ent->animcache_vertex3fbuffer = NULL;
4470                 ent->animcache_vertexmeshbuffer = NULL;
4471         }
4472 }
4473
4474 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4475 {
4476         int i;
4477
4478         // check if we need the meshbuffers
4479         if (!vid.useinterleavedarrays)
4480                 return;
4481
4482         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4483                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4484         // TODO: upload vertex3f buffer?
4485         if (ent->animcache_vertexmesh)
4486         {
4487                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4488                 for (i = 0;i < numvertices;i++)
4489                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4490                 if (ent->animcache_svector3f)
4491                         for (i = 0;i < numvertices;i++)
4492                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4493                 if (ent->animcache_tvector3f)
4494                         for (i = 0;i < numvertices;i++)
4495                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4496                 if (ent->animcache_normal3f)
4497                         for (i = 0;i < numvertices;i++)
4498                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4499                 // TODO: upload vertexmeshbuffer?
4500         }
4501 }
4502
4503 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4504 {
4505         dp_model_t *model = ent->model;
4506         int numvertices;
4507         // see if it's already cached this frame
4508         if (ent->animcache_vertex3f)
4509         {
4510                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4511                 if (wantnormals || wanttangents)
4512                 {
4513                         if (ent->animcache_normal3f)
4514                                 wantnormals = false;
4515                         if (ent->animcache_svector3f)
4516                                 wanttangents = false;
4517                         if (wantnormals || wanttangents)
4518                         {
4519                                 numvertices = model->surfmesh.num_vertices;
4520                                 if (wantnormals)
4521                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4522                                 if (wanttangents)
4523                                 {
4524                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4525                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4526                                 }
4527                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4528                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4529                         }
4530                 }
4531         }
4532         else
4533         {
4534                 // see if this ent is worth caching
4535                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4536                         return false;
4537                 // get some memory for this entity and generate mesh data
4538                 numvertices = model->surfmesh.num_vertices;
4539                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4540                 if (wantnormals)
4541                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4542                 if (wanttangents)
4543                 {
4544                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4545                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4546                 }
4547                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4548                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4549         }
4550         return true;
4551 }
4552
4553 void R_AnimCache_CacheVisibleEntities(void)
4554 {
4555         int i;
4556         qboolean wantnormals = true;
4557         qboolean wanttangents = !r_showsurfaces.integer;
4558
4559         switch(vid.renderpath)
4560         {
4561         case RENDERPATH_GL20:
4562         case RENDERPATH_D3D9:
4563         case RENDERPATH_D3D10:
4564         case RENDERPATH_D3D11:
4565         case RENDERPATH_GLES2:
4566                 break;
4567         case RENDERPATH_GL13:
4568         case RENDERPATH_GL11:
4569                 wanttangents = false;
4570                 break;
4571         case RENDERPATH_SOFT:
4572                 break;
4573         }
4574
4575         if (r_shownormals.integer)
4576                 wanttangents = wantnormals = true;
4577
4578         // TODO: thread this
4579         // NOTE: R_PrepareRTLights() also caches entities
4580
4581         for (i = 0;i < r_refdef.scene.numentities;i++)
4582                 if (r_refdef.viewcache.entityvisible[i])
4583                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4584 }
4585
4586 //==================================================================================
4587
4588 static void R_View_UpdateEntityLighting (void)
4589 {
4590         int i;
4591         entity_render_t *ent;
4592         vec3_t tempdiffusenormal, avg;
4593         vec_t f, fa, fd, fdd;
4594         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4595
4596         for (i = 0;i < r_refdef.scene.numentities;i++)
4597         {
4598                 ent = r_refdef.scene.entities[i];
4599
4600                 // skip unseen models
4601                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4602                         continue;
4603
4604                 // skip bsp models
4605                 if (ent->model && ent->model->brush.num_leafs)
4606                 {
4607                         // TODO: use modellight for r_ambient settings on world?
4608                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4609                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4610                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4611                         continue;
4612                 }
4613
4614                 // fetch the lighting from the worldmodel data
4615                 VectorClear(ent->modellight_ambient);
4616                 VectorClear(ent->modellight_diffuse);
4617                 VectorClear(tempdiffusenormal);
4618                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4619                 {
4620                         vec3_t org;
4621                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4622
4623                         // complete lightning for lit sprites
4624                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4625                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4626                         {
4627                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4628                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4629                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4630                         }
4631                         else
4632                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4633
4634                         if(ent->flags & RENDER_EQUALIZE)
4635                         {
4636                                 // first fix up ambient lighting...
4637                                 if(r_equalize_entities_minambient.value > 0)
4638                                 {
4639                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4640                                         if(fd > 0)
4641                                         {
4642                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4643                                                 if(fa < r_equalize_entities_minambient.value * fd)
4644                                                 {
4645                                                         // solve:
4646                                                         //   fa'/fd' = minambient
4647                                                         //   fa'+0.25*fd' = fa+0.25*fd
4648                                                         //   ...
4649                                                         //   fa' = fd' * minambient
4650                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4651                                                         //   ...
4652                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4653                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4654                                                         //   ...
4655                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4656                                                         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
4657                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4658                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4659                                                 }
4660                                         }
4661                                 }
4662
4663                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4664                                 {
4665                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4666                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4667                                         f = fa + 0.25 * fd;
4668                                         if(f > 0)
4669                                         {
4670                                                 // adjust brightness and saturation to target
4671                                                 avg[0] = avg[1] = avg[2] = fa / f;
4672                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4673                                                 avg[0] = avg[1] = avg[2] = fd / f;
4674                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4675                                         }
4676                                 }
4677                         }
4678                 }
4679                 else // highly rare
4680                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4681
4682                 // move the light direction into modelspace coordinates for lighting code
4683                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4684                 if(VectorLength2(ent->modellight_lightdir) == 0)
4685                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4686                 VectorNormalize(ent->modellight_lightdir);
4687         }
4688 }
4689
4690 #define MAX_LINEOFSIGHTTRACES 64
4691
4692 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4693 {
4694         int i;
4695         vec3_t boxmins, boxmaxs;
4696         vec3_t start;
4697         vec3_t end;
4698         dp_model_t *model = r_refdef.scene.worldmodel;
4699
4700         if (!model || !model->brush.TraceLineOfSight)
4701                 return true;
4702
4703         // expand the box a little
4704         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4705         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4706         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4707         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4708         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4709         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4710
4711         // return true if eye is inside enlarged box
4712         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4713                 return true;
4714
4715         // try center
4716         VectorCopy(eye, start);
4717         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4718         if (model->brush.TraceLineOfSight(model, start, end))
4719                 return true;
4720
4721         // try various random positions
4722         for (i = 0;i < numsamples;i++)
4723         {
4724                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4725                 if (model->brush.TraceLineOfSight(model, start, end))
4726                         return true;
4727         }
4728
4729         return false;
4730 }
4731
4732
4733 static void R_View_UpdateEntityVisible (void)
4734 {
4735         int i;
4736         int renderimask;
4737         int samples;
4738         entity_render_t *ent;
4739
4740         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4741                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4742                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4743                 :                                                          RENDER_EXTERIORMODEL;
4744         if (!r_drawviewmodel.integer)
4745                 renderimask |= RENDER_VIEWMODEL;
4746         if (!r_drawexteriormodel.integer)
4747                 renderimask |= RENDER_EXTERIORMODEL;
4748         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4749         {
4750                 // worldmodel can check visibility
4751                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4752                 for (i = 0;i < r_refdef.scene.numentities;i++)
4753                 {
4754                         ent = r_refdef.scene.entities[i];
4755                         if (!(ent->flags & renderimask))
4756                         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)))
4757                         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))
4758                                 r_refdef.viewcache.entityvisible[i] = true;
4759                 }
4760                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4761                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4762                 {
4763                         for (i = 0;i < r_refdef.scene.numentities;i++)
4764                         {
4765                                 ent = r_refdef.scene.entities[i];
4766                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4767                                 {
4768                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4769                                         if (samples < 0)
4770                                                 continue; // temp entities do pvs only
4771                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4772                                                 ent->last_trace_visibility = realtime;
4773                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4774                                                 r_refdef.viewcache.entityvisible[i] = 0;
4775                                 }
4776                         }
4777                 }
4778         }
4779         else
4780         {
4781                 // no worldmodel or it can't check visibility
4782                 for (i = 0;i < r_refdef.scene.numentities;i++)
4783                 {
4784                         ent = r_refdef.scene.entities[i];
4785                         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));
4786                 }
4787         }
4788 }
4789
4790 /// only used if skyrendermasked, and normally returns false
4791 int R_DrawBrushModelsSky (void)
4792 {
4793         int i, sky;
4794         entity_render_t *ent;
4795
4796         sky = false;
4797         for (i = 0;i < r_refdef.scene.numentities;i++)
4798         {
4799                 if (!r_refdef.viewcache.entityvisible[i])
4800                         continue;
4801                 ent = r_refdef.scene.entities[i];
4802                 if (!ent->model || !ent->model->DrawSky)
4803                         continue;
4804                 ent->model->DrawSky(ent);
4805                 sky = true;
4806         }
4807         return sky;
4808 }
4809
4810 static void R_DrawNoModel(entity_render_t *ent);
4811 static void R_DrawModels(void)
4812 {
4813         int i;
4814         entity_render_t *ent;
4815
4816         for (i = 0;i < r_refdef.scene.numentities;i++)
4817         {
4818                 if (!r_refdef.viewcache.entityvisible[i])
4819                         continue;
4820                 ent = r_refdef.scene.entities[i];
4821                 r_refdef.stats.entities++;
4822                 if (ent->model && ent->model->Draw != NULL)
4823                         ent->model->Draw(ent);
4824                 else
4825                         R_DrawNoModel(ent);
4826         }
4827 }
4828
4829 static void R_DrawModelsDepth(void)
4830 {
4831         int i;
4832         entity_render_t *ent;
4833
4834         for (i = 0;i < r_refdef.scene.numentities;i++)
4835         {
4836                 if (!r_refdef.viewcache.entityvisible[i])
4837                         continue;
4838                 ent = r_refdef.scene.entities[i];
4839                 if (ent->model && ent->model->DrawDepth != NULL)
4840                         ent->model->DrawDepth(ent);
4841         }
4842 }
4843
4844 static void R_DrawModelsDebug(void)
4845 {
4846         int i;
4847         entity_render_t *ent;
4848
4849         for (i = 0;i < r_refdef.scene.numentities;i++)
4850         {
4851                 if (!r_refdef.viewcache.entityvisible[i])
4852                         continue;
4853                 ent = r_refdef.scene.entities[i];
4854                 if (ent->model && ent->model->DrawDebug != NULL)
4855                         ent->model->DrawDebug(ent);
4856         }
4857 }
4858
4859 static void R_DrawModelsAddWaterPlanes(void)
4860 {
4861         int i;
4862         entity_render_t *ent;
4863
4864         for (i = 0;i < r_refdef.scene.numentities;i++)
4865         {
4866                 if (!r_refdef.viewcache.entityvisible[i])
4867                         continue;
4868                 ent = r_refdef.scene.entities[i];
4869                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4870                         ent->model->DrawAddWaterPlanes(ent);
4871         }
4872 }
4873
4874 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4875 {
4876         if (r_hdr_irisadaptation.integer)
4877         {
4878                 vec3_t ambient;
4879                 vec3_t diffuse;
4880                 vec3_t diffusenormal;
4881                 vec_t brightness;
4882                 vec_t goal;
4883                 vec_t adjust;
4884                 vec_t current;
4885                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4886                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4887                 brightness = max(0.0000001f, brightness);
4888                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4889                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4890                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4891                 current = r_hdr_irisadaptation_value.value;
4892                 if (current < goal)
4893                         current = min(current + adjust, goal);
4894                 else if (current > goal)
4895                         current = max(current - adjust, goal);
4896                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4897                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4898         }
4899         else if (r_hdr_irisadaptation_value.value != 1.0f)
4900                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4901 }
4902
4903 static void R_View_SetFrustum(const int *scissor)
4904 {
4905         int i;
4906         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4907         vec3_t forward, left, up, origin, v;
4908
4909         if(scissor)
4910         {
4911                 // flipped x coordinates (because x points left here)
4912                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4913                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4914
4915                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4916                 switch(vid.renderpath)
4917                 {
4918                         case RENDERPATH_D3D9:
4919                         case RENDERPATH_D3D10:
4920                         case RENDERPATH_D3D11:
4921                         case RENDERPATH_SOFT:
4922                                 // non-flipped y coordinates
4923                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4924                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4925                                 break;
4926                         case RENDERPATH_GL11:
4927                         case RENDERPATH_GL13:
4928                         case RENDERPATH_GL20:
4929                         case RENDERPATH_GLES2:
4930                                 // non-flipped y coordinates
4931                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4932                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4933                                 break;
4934                 }
4935         }
4936
4937         // we can't trust r_refdef.view.forward and friends in reflected scenes
4938         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4939
4940 #if 0
4941         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4942         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4943         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4944         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4945         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4946         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4947         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4948         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4949         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4950         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4951         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4952         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4953 #endif
4954
4955 #if 0
4956         zNear = r_refdef.nearclip;
4957         nudge = 1.0 - 1.0 / (1<<23);
4958         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4959         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4960         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4961         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4962         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4963         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4964         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4965         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4966 #endif
4967
4968
4969
4970 #if 0
4971         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4972         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4973         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4974         r_refdef.view.frustum[0].dist = m[15] - m[12];
4975
4976         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4977         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4978         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4979         r_refdef.view.frustum[1].dist = m[15] + m[12];
4980
4981         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4982         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4983         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4984         r_refdef.view.frustum[2].dist = m[15] - m[13];
4985
4986         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4987         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4988         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4989         r_refdef.view.frustum[3].dist = m[15] + m[13];
4990
4991         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4992         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4993         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4994         r_refdef.view.frustum[4].dist = m[15] - m[14];
4995
4996         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4997         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4998         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4999         r_refdef.view.frustum[5].dist = m[15] + m[14];
5000 #endif
5001
5002         if (r_refdef.view.useperspective)
5003         {
5004                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5005                 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]);
5006                 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]);
5007                 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]);
5008                 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]);
5009
5010                 // then the normals from the corners relative to origin
5011                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5012                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5013                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5014                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5015
5016                 // in a NORMAL view, forward cross left == up
5017                 // in a REFLECTED view, forward cross left == down
5018                 // so our cross products above need to be adjusted for a left handed coordinate system
5019                 CrossProduct(forward, left, v);
5020                 if(DotProduct(v, up) < 0)
5021                 {
5022                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5023                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5024                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5025                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5026                 }
5027
5028                 // Leaving those out was a mistake, those were in the old code, and they
5029                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5030                 // I couldn't reproduce it after adding those normalizations. --blub
5031                 VectorNormalize(r_refdef.view.frustum[0].normal);
5032                 VectorNormalize(r_refdef.view.frustum[1].normal);
5033                 VectorNormalize(r_refdef.view.frustum[2].normal);
5034                 VectorNormalize(r_refdef.view.frustum[3].normal);
5035
5036                 // make the corners absolute
5037                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5038                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5039                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5040                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5041
5042                 // one more normal
5043                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5044
5045                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5046                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5047                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5048                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5049                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5050         }
5051         else
5052         {
5053                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5054                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5055                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5056                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5057                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5058                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5059                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5060                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5061                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5062                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5063         }
5064         r_refdef.view.numfrustumplanes = 5;
5065
5066         if (r_refdef.view.useclipplane)
5067         {
5068                 r_refdef.view.numfrustumplanes = 6;
5069                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5070         }
5071
5072         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5073                 PlaneClassify(r_refdef.view.frustum + i);
5074
5075         // LordHavoc: note to all quake engine coders, Quake had a special case
5076         // for 90 degrees which assumed a square view (wrong), so I removed it,
5077         // Quake2 has it disabled as well.
5078
5079         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5080         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5081         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5082         //PlaneClassify(&frustum[0]);
5083
5084         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5085         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5086         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5087         //PlaneClassify(&frustum[1]);
5088
5089         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5090         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5091         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5092         //PlaneClassify(&frustum[2]);
5093
5094         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5095         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5096         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5097         //PlaneClassify(&frustum[3]);
5098
5099         // nearclip plane
5100         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5101         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5102         //PlaneClassify(&frustum[4]);
5103 }
5104
5105 void R_View_UpdateWithScissor(const int *myscissor)
5106 {
5107         R_Main_ResizeViewCache();
5108         R_View_SetFrustum(myscissor);
5109         R_View_WorldVisibility(r_refdef.view.useclipplane);
5110         R_View_UpdateEntityVisible();
5111         R_View_UpdateEntityLighting();
5112 }
5113
5114 void R_View_Update(void)
5115 {
5116         R_Main_ResizeViewCache();
5117         R_View_SetFrustum(NULL);
5118         R_View_WorldVisibility(r_refdef.view.useclipplane);
5119         R_View_UpdateEntityVisible();
5120         R_View_UpdateEntityLighting();
5121 }
5122
5123 void R_Mesh_SetMainRenderTargets(void)
5124 {
5125         if (r_bloomstate.fbo_framebuffer)
5126                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5127         else
5128                 R_Mesh_ResetRenderTargets();
5129 }
5130
5131 void R_SetupView(qboolean allowwaterclippingplane)
5132 {
5133         const float *customclipplane = NULL;
5134         float plane[4];
5135         int scaledwidth, scaledheight;
5136         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5137         {
5138                 // LordHavoc: couldn't figure out how to make this approach the
5139                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5140                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5141                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5142                         dist = r_refdef.view.clipplane.dist;
5143                 plane[0] = r_refdef.view.clipplane.normal[0];
5144                 plane[1] = r_refdef.view.clipplane.normal[1];
5145                 plane[2] = r_refdef.view.clipplane.normal[2];
5146                 plane[3] = dist;
5147                 customclipplane = plane;
5148         }
5149
5150         scaledwidth = (int)ceil(r_refdef.view.width * bound(0.125f, r_viewscale.value, 1.0f));
5151         scaledheight = (int)ceil(r_refdef.view.height * bound(0.125f, r_viewscale.value, 1.0f));
5152         if (!r_refdef.view.useperspective)
5153                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -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);
5154         else if (vid.stencil && r_useinfinitefarclip.integer)
5155                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5156         else
5157                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5158         R_Mesh_SetMainRenderTargets();
5159         R_SetViewport(&r_refdef.view.viewport);
5160 }
5161
5162 void R_EntityMatrix(const matrix4x4_t *matrix)
5163 {
5164         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5165         {
5166                 gl_modelmatrixchanged = false;
5167                 gl_modelmatrix = *matrix;
5168                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5169                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5170                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5171                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5172                 CHECKGLERROR
5173                 switch(vid.renderpath)
5174                 {
5175                 case RENDERPATH_D3D9:
5176 #ifdef SUPPORTD3D
5177                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5178                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5179 #endif
5180                         break;
5181                 case RENDERPATH_D3D10:
5182                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5183                         break;
5184                 case RENDERPATH_D3D11:
5185                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5186                         break;
5187                 case RENDERPATH_GL13:
5188                 case RENDERPATH_GL11:
5189                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5190                         break;
5191                 case RENDERPATH_SOFT:
5192                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5193                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5194                         break;
5195                 case RENDERPATH_GL20:
5196                 case RENDERPATH_GLES2:
5197                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5198                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5199                         break;
5200                 }
5201         }
5202 }
5203
5204 void R_ResetViewRendering2D(void)
5205 {
5206         r_viewport_t viewport;
5207         DrawQ_Finish();
5208
5209         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5210         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);
5211         R_Mesh_ResetRenderTargets();
5212         R_SetViewport(&viewport);
5213         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5214         GL_Color(1, 1, 1, 1);
5215         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5216         GL_BlendFunc(GL_ONE, GL_ZERO);
5217         GL_ScissorTest(false);
5218         GL_DepthMask(false);
5219         GL_DepthRange(0, 1);
5220         GL_DepthTest(false);
5221         GL_DepthFunc(GL_LEQUAL);
5222         R_EntityMatrix(&identitymatrix);
5223         R_Mesh_ResetTextureState();
5224         GL_PolygonOffset(0, 0);
5225         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5226         switch(vid.renderpath)
5227         {
5228         case RENDERPATH_GL11:
5229         case RENDERPATH_GL13:
5230         case RENDERPATH_GL20:
5231         case RENDERPATH_GLES2:
5232                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5233                 break;
5234         case RENDERPATH_D3D9:
5235         case RENDERPATH_D3D10:
5236         case RENDERPATH_D3D11:
5237         case RENDERPATH_SOFT:
5238                 break;
5239         }
5240         GL_CullFace(GL_NONE);
5241 }
5242
5243 void R_ResetViewRendering3D(void)
5244 {
5245         DrawQ_Finish();
5246
5247         R_SetupView(true);
5248         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5249         GL_Color(1, 1, 1, 1);
5250         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5251         GL_BlendFunc(GL_ONE, GL_ZERO);
5252         GL_ScissorTest(true);
5253         GL_DepthMask(true);
5254         GL_DepthRange(0, 1);
5255         GL_DepthTest(true);
5256         GL_DepthFunc(GL_LEQUAL);
5257         R_EntityMatrix(&identitymatrix);
5258         R_Mesh_ResetTextureState();
5259         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5260         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5261         switch(vid.renderpath)
5262         {
5263         case RENDERPATH_GL11:
5264         case RENDERPATH_GL13:
5265         case RENDERPATH_GL20:
5266         case RENDERPATH_GLES2:
5267                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5268                 break;
5269         case RENDERPATH_D3D9:
5270         case RENDERPATH_D3D10:
5271         case RENDERPATH_D3D11:
5272         case RENDERPATH_SOFT:
5273                 break;
5274         }
5275         GL_CullFace(r_refdef.view.cullface_back);
5276 }
5277
5278 /*
5279 ================
5280 R_RenderView_UpdateViewVectors
5281 ================
5282 */
5283 static void R_RenderView_UpdateViewVectors(void)
5284 {
5285         // break apart the view matrix into vectors for various purposes
5286         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5287         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5288         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5289         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5290         // make an inverted copy of the view matrix for tracking sprites
5291         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5292 }
5293
5294 void R_RenderScene(void);
5295 void R_RenderWaterPlanes(void);
5296
5297 static void R_Water_StartFrame(void)
5298 {
5299         int i;
5300         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5301         r_waterstate_waterplane_t *p;
5302
5303         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5304                 return;
5305
5306         switch(vid.renderpath)
5307         {
5308         case RENDERPATH_GL20:
5309         case RENDERPATH_D3D9:
5310         case RENDERPATH_D3D10:
5311         case RENDERPATH_D3D11:
5312         case RENDERPATH_SOFT:
5313         case RENDERPATH_GLES2:
5314                 break;
5315         case RENDERPATH_GL13:
5316         case RENDERPATH_GL11:
5317                 return;
5318         }
5319
5320         // set waterwidth and waterheight to the water resolution that will be
5321         // used (often less than the screen resolution for faster rendering)
5322         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5323         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5324
5325         // calculate desired texture sizes
5326         // can't use water if the card does not support the texture size
5327         if (!r_water.integer || r_showsurfaces.integer)
5328                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5329         else if (vid.support.arb_texture_non_power_of_two)
5330         {
5331                 texturewidth = waterwidth;
5332                 textureheight = waterheight;
5333                 camerawidth = waterwidth;
5334                 cameraheight = waterheight;
5335         }
5336         else
5337         {
5338                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5339                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5340                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5341                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5342         }
5343
5344         // allocate textures as needed
5345         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5346         {
5347                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5348                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5349                 {
5350                         if (p->texture_refraction)
5351                                 R_FreeTexture(p->texture_refraction);
5352                         p->texture_refraction = NULL;
5353                         if (p->texture_reflection)
5354                                 R_FreeTexture(p->texture_reflection);
5355                         p->texture_reflection = NULL;
5356                         if (p->texture_camera)
5357                                 R_FreeTexture(p->texture_camera);
5358                         p->texture_camera = NULL;
5359                 }
5360                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5361                 r_waterstate.texturewidth = texturewidth;
5362                 r_waterstate.textureheight = textureheight;
5363                 r_waterstate.camerawidth = camerawidth;
5364                 r_waterstate.cameraheight = cameraheight;
5365         }
5366
5367         if (r_waterstate.texturewidth)
5368         {
5369                 r_waterstate.enabled = true;
5370
5371                 // when doing a reduced render (HDR) we want to use a smaller area
5372                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5373                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5374
5375                 // set up variables that will be used in shader setup
5376                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5377                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5378                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5379                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5380         }
5381
5382         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5383         r_waterstate.numwaterplanes = 0;
5384 }
5385
5386 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5387 {
5388         int triangleindex, planeindex;
5389         const int *e;
5390         vec3_t vert[3];
5391         vec3_t normal;
5392         vec3_t center;
5393         mplane_t plane;
5394         r_waterstate_waterplane_t *p;
5395         texture_t *t = R_GetCurrentTexture(surface->texture);
5396
5397         // just use the first triangle with a valid normal for any decisions
5398         VectorClear(normal);
5399         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5400         {
5401                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5402                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5403                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5404                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5405                 if (VectorLength2(normal) >= 0.001)
5406                         break;
5407         }
5408
5409         VectorCopy(normal, plane.normal);
5410         VectorNormalize(plane.normal);
5411         plane.dist = DotProduct(vert[0], plane.normal);
5412         PlaneClassify(&plane);
5413         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5414         {
5415                 // skip backfaces (except if nocullface is set)
5416                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5417                         return;
5418                 VectorNegate(plane.normal, plane.normal);
5419                 plane.dist *= -1;
5420                 PlaneClassify(&plane);
5421         }
5422
5423
5424         // find a matching plane if there is one
5425         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5426                 if(p->camera_entity == t->camera_entity)
5427                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5428                                 break;
5429         if (planeindex >= r_waterstate.maxwaterplanes)
5430                 return; // nothing we can do, out of planes
5431
5432         // if this triangle does not fit any known plane rendered this frame, add one
5433         if (planeindex >= r_waterstate.numwaterplanes)
5434         {
5435                 // store the new plane
5436                 r_waterstate.numwaterplanes++;
5437                 p->plane = plane;
5438                 // clear materialflags and pvs
5439                 p->materialflags = 0;
5440                 p->pvsvalid = false;
5441                 p->camera_entity = t->camera_entity;
5442                 VectorCopy(surface->mins, p->mins);
5443                 VectorCopy(surface->maxs, p->maxs);
5444         }
5445         else
5446         {
5447                 // merge mins/maxs
5448                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5449                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5450                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5451                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5452                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5453                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5454         }
5455         // merge this surface's materialflags into the waterplane
5456         p->materialflags |= t->currentmaterialflags;
5457         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5458         {
5459                 // merge this surface's PVS into the waterplane
5460                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5461                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5462                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5463                 {
5464                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5465                         p->pvsvalid = true;
5466                 }
5467         }
5468 }
5469
5470 static void R_Water_ProcessPlanes(void)
5471 {
5472         int myscissor[4];
5473         r_refdef_view_t originalview;
5474         r_refdef_view_t myview;
5475         int planeindex;
5476         r_waterstate_waterplane_t *p;
5477         vec3_t visorigin;
5478
5479         originalview = r_refdef.view;
5480
5481         // make sure enough textures are allocated
5482         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5483         {
5484                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5485                 {
5486                         if (!p->texture_refraction)
5487                                 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);
5488                         if (!p->texture_refraction)
5489                                 goto error;
5490                 }
5491                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5492                 {
5493                         if (!p->texture_camera)
5494                                 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);
5495                         if (!p->texture_camera)
5496                                 goto error;
5497                 }
5498
5499                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5500                 {
5501                         if (!p->texture_reflection)
5502                                 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);
5503                         if (!p->texture_reflection)
5504                                 goto error;
5505                 }
5506         }
5507
5508         // render views
5509         r_refdef.view = originalview;
5510         r_refdef.view.showdebug = false;
5511         r_refdef.view.width = r_waterstate.waterwidth;
5512         r_refdef.view.height = r_waterstate.waterheight;
5513         r_refdef.view.useclipplane = true;
5514         myview = r_refdef.view;
5515         r_waterstate.renderingscene = true;
5516         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5517         {
5518                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5519                 {
5520                         r_refdef.view = myview;
5521                         if(r_water_scissormode.integer)
5522                         {
5523                                 R_SetupView(true);
5524                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5525                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5526                         }
5527
5528                         // render reflected scene and copy into texture
5529                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5530                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5531                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5532                         r_refdef.view.clipplane = p->plane;
5533
5534                         // reverse the cullface settings for this render
5535                         r_refdef.view.cullface_front = GL_FRONT;
5536                         r_refdef.view.cullface_back = GL_BACK;
5537                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5538                         {
5539                                 r_refdef.view.usecustompvs = true;
5540                                 if (p->pvsvalid)
5541                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5542                                 else
5543                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5544                         }
5545
5546                         R_ResetViewRendering3D();
5547                         R_ClearScreen(r_refdef.fogenabled);
5548                         if(r_water_scissormode.integer & 2)
5549                                 R_View_UpdateWithScissor(myscissor);
5550                         else
5551                                 R_View_Update();
5552                         if(r_water_scissormode.integer & 1)
5553                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5554                         R_RenderScene();
5555
5556                         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);
5557                 }
5558
5559                 // render the normal view scene and copy into texture
5560                 // (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)
5561                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5562                 {
5563                         r_refdef.view = myview;
5564                         if(r_water_scissormode.integer)
5565                         {
5566                                 R_SetupView(true);
5567                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5568                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5569                         }
5570
5571                         r_waterstate.renderingrefraction = true;
5572
5573                         r_refdef.view.clipplane = p->plane;
5574                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5575                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5576
5577                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5578                         {
5579                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5580                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5581                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5582                                 R_RenderView_UpdateViewVectors();
5583                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5584                                 {
5585                                         r_refdef.view.usecustompvs = true;
5586                                         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);
5587                                 }
5588                         }
5589
5590                         PlaneClassify(&r_refdef.view.clipplane);
5591
5592                         R_ResetViewRendering3D();
5593                         R_ClearScreen(r_refdef.fogenabled);
5594                         if(r_water_scissormode.integer & 2)
5595                                 R_View_UpdateWithScissor(myscissor);
5596                         else
5597                                 R_View_Update();
5598                         if(r_water_scissormode.integer & 1)
5599                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5600                         R_RenderScene();
5601
5602                         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);
5603                         r_waterstate.renderingrefraction = false;
5604                 }
5605                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5606                 {
5607                         r_refdef.view = myview;
5608
5609                         r_refdef.view.clipplane = p->plane;
5610                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5611                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5612
5613                         r_refdef.view.width = r_waterstate.camerawidth;
5614                         r_refdef.view.height = r_waterstate.cameraheight;
5615                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5616                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5617
5618                         if(p->camera_entity)
5619                         {
5620                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5621                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5622                         }
5623
5624                         // note: all of the view is used for displaying... so
5625                         // there is no use in scissoring
5626
5627                         // reverse the cullface settings for this render
5628                         r_refdef.view.cullface_front = GL_FRONT;
5629                         r_refdef.view.cullface_back = GL_BACK;
5630                         // also reverse the view matrix
5631                         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
5632                         R_RenderView_UpdateViewVectors();
5633                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5634                         {
5635                                 r_refdef.view.usecustompvs = true;
5636                                 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);
5637                         }
5638                         
5639                         // camera needs no clipplane
5640                         r_refdef.view.useclipplane = false;
5641
5642                         PlaneClassify(&r_refdef.view.clipplane);
5643
5644                         R_ResetViewRendering3D();
5645                         R_ClearScreen(r_refdef.fogenabled);
5646                         R_View_Update();
5647                         R_RenderScene();
5648
5649                         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);
5650                         r_waterstate.renderingrefraction = false;
5651                 }
5652
5653         }
5654         r_waterstate.renderingscene = false;
5655         r_refdef.view = originalview;
5656         R_ResetViewRendering3D();
5657         R_ClearScreen(r_refdef.fogenabled);
5658         R_View_Update();
5659         return;
5660 error:
5661         r_refdef.view = originalview;
5662         r_waterstate.renderingscene = false;
5663         Cvar_SetValueQuick(&r_water, 0);
5664         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5665         return;
5666 }
5667
5668 void R_Bloom_StartFrame(void)
5669 {
5670         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5671         textype_t textype;
5672
5673         switch(vid.renderpath)
5674         {
5675         case RENDERPATH_GL20:
5676         case RENDERPATH_D3D9:
5677         case RENDERPATH_D3D10:
5678         case RENDERPATH_D3D11:
5679         case RENDERPATH_SOFT:
5680         case RENDERPATH_GLES2:
5681                 break;
5682         case RENDERPATH_GL13:
5683         case RENDERPATH_GL11:
5684                 return;
5685         }
5686
5687         // set bloomwidth and bloomheight to the bloom resolution that will be
5688         // used (often less than the screen resolution for faster rendering)
5689         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5690         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5691         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5692         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5693         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5694
5695         // calculate desired texture sizes
5696         if (vid.support.arb_texture_non_power_of_two)
5697         {
5698                 screentexturewidth = vid.width;
5699                 screentextureheight = vid.height;
5700                 bloomtexturewidth = r_bloomstate.bloomwidth;
5701                 bloomtextureheight = r_bloomstate.bloomheight;
5702         }
5703         else
5704         {
5705                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5706                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5707                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5708                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5709         }
5710
5711         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))
5712         {
5713                 Cvar_SetValueQuick(&r_hdr, 0);
5714                 Cvar_SetValueQuick(&r_bloom, 0);
5715                 Cvar_SetValueQuick(&r_motionblur, 0);
5716                 Cvar_SetValueQuick(&r_damageblur, 0);
5717         }
5718
5719         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)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f)
5720                 screentexturewidth = screentextureheight = 0;
5721         if (!r_hdr.integer && !r_bloom.integer)
5722                 bloomtexturewidth = bloomtextureheight = 0;
5723
5724         textype = TEXTYPE_COLORBUFFER;
5725         switch (vid.renderpath)
5726         {
5727         case RENDERPATH_GL20:
5728         case RENDERPATH_GLES2:
5729                 if (vid.support.ext_framebuffer_object)
5730                 {
5731                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5732                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5733                 }
5734                 break;
5735         case RENDERPATH_D3D9:
5736         case RENDERPATH_D3D10:
5737         case RENDERPATH_D3D11:
5738         case RENDERPATH_SOFT:
5739         case RENDERPATH_GL13:
5740         case RENDERPATH_GL11:
5741                 break;
5742         }
5743
5744         // allocate textures as needed
5745         if (r_bloomstate.screentexturewidth != screentexturewidth
5746          || r_bloomstate.screentextureheight != screentextureheight
5747          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5748          || r_bloomstate.bloomtextureheight != bloomtextureheight
5749          || r_bloomstate.texturetype != textype
5750          || r_bloomstate.viewfbo != r_viewfbo.integer)
5751         {
5752                 if (r_bloomstate.texture_bloom)
5753                         R_FreeTexture(r_bloomstate.texture_bloom);
5754                 r_bloomstate.texture_bloom = NULL;
5755                 if (r_bloomstate.texture_screen)
5756                         R_FreeTexture(r_bloomstate.texture_screen);
5757                 r_bloomstate.texture_screen = NULL;
5758                 if (r_bloomstate.fbo_framebuffer)
5759                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5760                 r_bloomstate.fbo_framebuffer = 0;
5761                 if (r_bloomstate.texture_framebuffercolor)
5762                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5763                 r_bloomstate.texture_framebuffercolor = NULL;
5764                 if (r_bloomstate.texture_framebufferdepth)
5765                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5766                 r_bloomstate.texture_framebufferdepth = NULL;
5767                 r_bloomstate.screentexturewidth = screentexturewidth;
5768                 r_bloomstate.screentextureheight = screentextureheight;
5769                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5770                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5771                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5772                 {
5773                         // FIXME: choose depth bits based on a cvar
5774                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5775                         r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5776                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5777                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5778                         // render depth into one texture and normalmap into the other
5779                         if (qglDrawBuffer)
5780                         {
5781                                 int status;
5782                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5783                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5784                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5785                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5786                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5787                         }
5788                 }
5789                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5790                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5791                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5792                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5793                 r_bloomstate.viewfbo = r_viewfbo.integer;
5794                 r_bloomstate.texturetype = textype;
5795         }
5796
5797         // when doing a reduced render (HDR) we want to use a smaller area
5798         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5799         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5800         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5801         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5802         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5803
5804         // set up a texcoord array for the full resolution screen image
5805         // (we have to keep this around to copy back during final render)
5806         r_bloomstate.screentexcoord2f[0] = 0;
5807         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.viewport.height    / (float)r_bloomstate.screentextureheight;
5808         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.viewport.width     / (float)r_bloomstate.screentexturewidth;
5809         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.viewport.height    / (float)r_bloomstate.screentextureheight;
5810         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.viewport.width     / (float)r_bloomstate.screentexturewidth;
5811         r_bloomstate.screentexcoord2f[5] = 0;
5812         r_bloomstate.screentexcoord2f[6] = 0;
5813         r_bloomstate.screentexcoord2f[7] = 0;
5814
5815         // set up a texcoord array for the reduced resolution bloom image
5816         // (which will be additive blended over the screen image)
5817         r_bloomstate.bloomtexcoord2f[0] = 0;
5818         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5819         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5820         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5821         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5822         r_bloomstate.bloomtexcoord2f[5] = 0;
5823         r_bloomstate.bloomtexcoord2f[6] = 0;
5824         r_bloomstate.bloomtexcoord2f[7] = 0;
5825
5826         switch(vid.renderpath)
5827         {
5828         case RENDERPATH_GL11:
5829         case RENDERPATH_GL13:
5830         case RENDERPATH_GL20:
5831         case RENDERPATH_SOFT:
5832         case RENDERPATH_GLES2:
5833                 break;
5834         case RENDERPATH_D3D9:
5835         case RENDERPATH_D3D10:
5836         case RENDERPATH_D3D11:
5837                 {
5838                         int i;
5839                         for (i = 0;i < 4;i++)
5840                         {
5841                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5842                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5843                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5844                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5845                         }
5846                 }
5847                 break;
5848         }
5849
5850         if (r_hdr.integer || r_bloom.integer)
5851         {
5852                 r_bloomstate.enabled = true;
5853                 r_bloomstate.hdr = r_hdr.integer != 0;
5854         }
5855
5856         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);
5857
5858         if (r_bloomstate.fbo_framebuffer)
5859                 r_refdef.view.clear = true;
5860 }
5861
5862 void R_Bloom_CopyBloomTexture(float colorscale)
5863 {
5864         r_refdef.stats.bloom++;
5865
5866         // scale down screen texture to the bloom texture size
5867         CHECKGLERROR
5868         R_Mesh_SetMainRenderTargets();
5869         R_SetViewport(&r_bloomstate.viewport);
5870         GL_BlendFunc(GL_ONE, GL_ZERO);
5871         GL_Color(colorscale, colorscale, colorscale, 1);
5872         // 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...
5873         switch(vid.renderpath)
5874         {
5875         case RENDERPATH_GL11:
5876         case RENDERPATH_GL13:
5877         case RENDERPATH_GL20:
5878         case RENDERPATH_SOFT:
5879         case RENDERPATH_GLES2:
5880                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5881                 break;
5882         case RENDERPATH_D3D9:
5883         case RENDERPATH_D3D10:
5884         case RENDERPATH_D3D11:
5885                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5886                 break;
5887         }
5888         // TODO: do boxfilter scale-down in shader?
5889         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5890         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5891         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5892
5893         // we now have a bloom image in the framebuffer
5894         // copy it into the bloom image texture for later processing
5895         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);
5896         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5897 }
5898
5899 void R_Bloom_CopyHDRTexture(void)
5900 {
5901         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);
5902         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5903 }
5904
5905 void R_Bloom_MakeTexture(void)
5906 {
5907         int x, range, dir;
5908         float xoffset, yoffset, r, brighten;
5909
5910         r_refdef.stats.bloom++;
5911
5912         R_ResetViewRendering2D();
5913
5914         // we have a bloom image in the framebuffer
5915         CHECKGLERROR
5916         R_SetViewport(&r_bloomstate.viewport);
5917
5918         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5919         {
5920                 x *= 2;
5921                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5922                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5923                 GL_Color(r,r,r,1);
5924                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5925                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5926                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5927                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5928
5929                 // copy the vertically blurred bloom view to a texture
5930                 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);
5931                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5932         }
5933
5934         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5935         brighten = r_bloom_brighten.value;
5936         if (r_hdr.integer)
5937                 brighten *= r_hdr_range.value;
5938         brighten = sqrt(brighten);
5939         if(range >= 1)
5940                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5941         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5942
5943         for (dir = 0;dir < 2;dir++)
5944         {
5945                 // blend on at multiple vertical offsets to achieve a vertical blur
5946                 // TODO: do offset blends using GLSL
5947                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5948                 GL_BlendFunc(GL_ONE, GL_ZERO);
5949                 for (x = -range;x <= range;x++)
5950                 {
5951                         if (!dir){xoffset = 0;yoffset = x;}
5952                         else {xoffset = x;yoffset = 0;}
5953                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5954                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5955                         // compute a texcoord array with the specified x and y offset
5956                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5957                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5958                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5959                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5960                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5961                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5962                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5963                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5964                         // this r value looks like a 'dot' particle, fading sharply to
5965                         // black at the edges
5966                         // (probably not realistic but looks good enough)
5967                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5968                         //r = brighten/(range*2+1);
5969                         r = brighten / (range * 2 + 1);
5970                         if(range >= 1)
5971                                 r *= (1 - x*x/(float)(range*range));
5972                         GL_Color(r, r, r, 1);
5973                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5974                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5975                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5976                         GL_BlendFunc(GL_ONE, GL_ONE);
5977                 }
5978
5979                 // copy the vertically blurred bloom view to a texture
5980                 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);
5981                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5982         }
5983 }
5984
5985 void R_HDR_RenderBloomTexture(void)
5986 {
5987         int oldwidth, oldheight;
5988         float oldcolorscale;
5989         qboolean oldwaterstate;
5990
5991         oldwaterstate = r_waterstate.enabled;
5992         oldcolorscale = r_refdef.view.colorscale;
5993         oldwidth = r_refdef.view.width;
5994         oldheight = r_refdef.view.height;
5995         r_refdef.view.width = r_bloomstate.bloomwidth;
5996         r_refdef.view.height = r_bloomstate.bloomheight;
5997
5998         if(r_hdr.integer < 2)
5999                 r_waterstate.enabled = false;
6000
6001         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6002         // TODO: add exposure compensation features
6003         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6004
6005         r_refdef.view.showdebug = false;
6006         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6007
6008         R_ResetViewRendering3D();
6009
6010         R_ClearScreen(r_refdef.fogenabled);
6011         if (r_timereport_active)
6012                 R_TimeReport("HDRclear");
6013
6014         R_View_Update();
6015         if (r_timereport_active)
6016                 R_TimeReport("visibility");
6017
6018         // only do secondary renders with HDR if r_hdr is 2 or higher
6019         r_waterstate.numwaterplanes = 0;
6020         if (r_waterstate.enabled)
6021                 R_RenderWaterPlanes();
6022
6023         r_refdef.view.showdebug = true;
6024         R_RenderScene();
6025         r_waterstate.numwaterplanes = 0;
6026
6027         R_ResetViewRendering2D();
6028
6029         R_Bloom_CopyHDRTexture();
6030         R_Bloom_MakeTexture();
6031
6032         // restore the view settings
6033         r_waterstate.enabled = oldwaterstate;
6034         r_refdef.view.width = oldwidth;
6035         r_refdef.view.height = oldheight;
6036         r_refdef.view.colorscale = oldcolorscale;
6037
6038         R_ResetViewRendering3D();
6039
6040         R_ClearScreen(r_refdef.fogenabled);
6041         if (r_timereport_active)
6042                 R_TimeReport("viewclear");
6043 }
6044
6045 static void R_BlendView(void)
6046 {
6047         unsigned int permutation;
6048         float uservecs[4][4];
6049
6050         switch (vid.renderpath)
6051         {
6052         case RENDERPATH_GL20:
6053         case RENDERPATH_D3D9:
6054         case RENDERPATH_D3D10:
6055         case RENDERPATH_D3D11:
6056         case RENDERPATH_SOFT:
6057         case RENDERPATH_GLES2:
6058                 permutation =
6059                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6060                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6061                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6062                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6063                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6064
6065                 if (r_bloomstate.texture_screen)
6066                 {
6067                         // make sure the buffer is available
6068                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6069
6070                         R_ResetViewRendering2D();
6071                         R_Mesh_SetMainRenderTargets();
6072
6073                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6074                         {
6075                                 // declare variables
6076                                 float speed;
6077                                 static float avgspeed;
6078
6079                                 speed = VectorLength(cl.movement_velocity);
6080
6081                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6082                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6083
6084                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6085                                 speed = bound(0, speed, 1);
6086                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6087
6088                                 // calculate values into a standard alpha
6089                                 cl.motionbluralpha = 1 - exp(-
6090                                                 (
6091                                                  (r_motionblur.value * speed / 80)
6092                                                  +
6093                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6094                                                 )
6095                                                 /
6096                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6097                                            );
6098
6099                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6100                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6101                                 // apply the blur
6102                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6103                                 {
6104                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6105                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6106                                         switch(vid.renderpath)
6107                                         {
6108                                         case RENDERPATH_GL11:
6109                                         case RENDERPATH_GL13:
6110                                         case RENDERPATH_GL20:
6111                                         case RENDERPATH_SOFT:
6112                                         case RENDERPATH_GLES2:
6113                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6114                                                 break;
6115                                         case RENDERPATH_D3D9:
6116                                         case RENDERPATH_D3D10:
6117                                         case RENDERPATH_D3D11:
6118                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6119                                                 break;
6120                                         }
6121                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6122                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6123                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6124                                 }
6125                         }
6126
6127                         // copy view into the screen texture
6128                         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);
6129                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6130                 }
6131                 else if (!r_bloomstate.texture_bloom)
6132                 {
6133                         // we may still have to do view tint...
6134                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6135                         {
6136                                 // apply a color tint to the whole view
6137                                 R_ResetViewRendering2D();
6138                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6139                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6140                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6141                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6142                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6143                         }
6144                         break; // no screen processing, no bloom, skip it
6145                 }
6146
6147                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6148                 {
6149                         // render simple bloom effect
6150                         // copy the screen and shrink it and darken it for the bloom process
6151                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6152                         // make the bloom texture
6153                         R_Bloom_MakeTexture();
6154                 }
6155
6156 #if _MSC_VER >= 1400
6157 #define sscanf sscanf_s
6158 #endif
6159                 memset(uservecs, 0, sizeof(uservecs));
6160                 if (r_glsl_postprocess_uservec1_enable.integer)
6161                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6162                 if (r_glsl_postprocess_uservec2_enable.integer)
6163                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6164                 if (r_glsl_postprocess_uservec3_enable.integer)
6165                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6166                 if (r_glsl_postprocess_uservec4_enable.integer)
6167                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6168
6169                 R_ResetViewRendering2D();
6170                 GL_Color(1, 1, 1, 1);
6171                 GL_BlendFunc(GL_ONE, GL_ZERO);
6172
6173                 switch(vid.renderpath)
6174                 {
6175                 case RENDERPATH_GL20:
6176                 case RENDERPATH_GLES2:
6177                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6178                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6179                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6180                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6181                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6182                         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]);
6183                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6184                         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]);
6185                         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]);
6186                         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]);
6187                         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]);
6188                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6189                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6190                         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);
6191                         break;
6192                 case RENDERPATH_D3D9:
6193 #ifdef SUPPORTD3D
6194                         // 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...
6195                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6196                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6197                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6198                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6199                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6200                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6201                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6202                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6203                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6204                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6205                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6206                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6207                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6208                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6209 #endif
6210                         break;
6211                 case RENDERPATH_D3D10:
6212                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6213                         break;
6214                 case RENDERPATH_D3D11:
6215                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6216                         break;
6217                 case RENDERPATH_SOFT:
6218                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6219                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6220                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6221                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6222                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6223                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6224                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6225                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6226                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6227                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6228                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6229                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6230                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6231                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6232                         break;
6233                 default:
6234                         break;
6235                 }
6236                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6237                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6238                 break;
6239         case RENDERPATH_GL13:
6240         case RENDERPATH_GL11:
6241                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6242                 {
6243                         // apply a color tint to the whole view
6244                         R_ResetViewRendering2D();
6245                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6246                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6247                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6248                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6249                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6250                 }
6251                 break;
6252         }
6253 }
6254
6255 matrix4x4_t r_waterscrollmatrix;
6256
6257 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6258 {
6259         if (r_refdef.fog_density)
6260         {
6261                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6262                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6263                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6264
6265                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6266                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6267                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6268                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6269
6270                 {
6271                         vec3_t fogvec;
6272                         VectorCopy(r_refdef.fogcolor, fogvec);
6273                         //   color.rgb *= ContrastBoost * SceneBrightness;
6274                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6275                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6276                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6277                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6278                 }
6279         }
6280 }
6281
6282 void R_UpdateVariables(void)
6283 {
6284         R_Textures_Frame();
6285
6286         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6287
6288         r_refdef.farclip = r_farclip_base.value;
6289         if (r_refdef.scene.worldmodel)
6290                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6291         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6292
6293         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6294                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6295         r_refdef.polygonfactor = 0;
6296         r_refdef.polygonoffset = 0;
6297         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6298         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6299
6300         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6301         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6302         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6303         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6304         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6305         if (FAKELIGHT_ENABLED)
6306         {
6307                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6308         }
6309         if (r_showsurfaces.integer)
6310         {
6311                 r_refdef.scene.rtworld = false;
6312                 r_refdef.scene.rtworldshadows = false;
6313                 r_refdef.scene.rtdlight = false;
6314                 r_refdef.scene.rtdlightshadows = false;
6315                 r_refdef.lightmapintensity = 0;
6316         }
6317
6318         if (gamemode == GAME_NEHAHRA)
6319         {
6320                 if (gl_fogenable.integer)
6321                 {
6322                         r_refdef.oldgl_fogenable = true;
6323                         r_refdef.fog_density = gl_fogdensity.value;
6324                         r_refdef.fog_red = gl_fogred.value;
6325                         r_refdef.fog_green = gl_foggreen.value;
6326                         r_refdef.fog_blue = gl_fogblue.value;
6327                         r_refdef.fog_alpha = 1;
6328                         r_refdef.fog_start = 0;
6329                         r_refdef.fog_end = gl_skyclip.value;
6330                         r_refdef.fog_height = 1<<30;
6331                         r_refdef.fog_fadedepth = 128;
6332                 }
6333                 else if (r_refdef.oldgl_fogenable)
6334                 {
6335                         r_refdef.oldgl_fogenable = false;
6336                         r_refdef.fog_density = 0;
6337                         r_refdef.fog_red = 0;
6338                         r_refdef.fog_green = 0;
6339                         r_refdef.fog_blue = 0;
6340                         r_refdef.fog_alpha = 0;
6341                         r_refdef.fog_start = 0;
6342                         r_refdef.fog_end = 0;
6343                         r_refdef.fog_height = 1<<30;
6344                         r_refdef.fog_fadedepth = 128;
6345                 }
6346         }
6347
6348         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6349         r_refdef.fog_start = max(0, r_refdef.fog_start);
6350         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6351
6352         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6353
6354         if (r_refdef.fog_density && r_drawfog.integer)
6355         {
6356                 r_refdef.fogenabled = true;
6357                 // this is the point where the fog reaches 0.9986 alpha, which we
6358                 // consider a good enough cutoff point for the texture
6359                 // (0.9986 * 256 == 255.6)
6360                 if (r_fog_exp2.integer)
6361                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6362                 else
6363                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6364                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6365                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6366                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6367                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6368                         R_BuildFogHeightTexture();
6369                 // fog color was already set
6370                 // update the fog texture
6371                 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)
6372                         R_BuildFogTexture();
6373                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6374                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6375         }
6376         else
6377                 r_refdef.fogenabled = false;
6378
6379         switch(vid.renderpath)
6380         {
6381         case RENDERPATH_GL20:
6382         case RENDERPATH_D3D9:
6383         case RENDERPATH_D3D10:
6384         case RENDERPATH_D3D11:
6385         case RENDERPATH_SOFT:
6386         case RENDERPATH_GLES2:
6387                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6388                 {
6389                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6390                         {
6391                                 // build GLSL gamma texture
6392 #define RAMPWIDTH 256
6393                                 unsigned short ramp[RAMPWIDTH * 3];
6394                                 unsigned char rampbgr[RAMPWIDTH][4];
6395                                 int i;
6396
6397                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6398
6399                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6400                                 for(i = 0; i < RAMPWIDTH; ++i)
6401                                 {
6402                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6403                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6404                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6405                                         rampbgr[i][3] = 0;
6406                                 }
6407                                 if (r_texture_gammaramps)
6408                                 {
6409                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6410                                 }
6411                                 else
6412                                 {
6413                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6414                                 }
6415                         }
6416                 }
6417                 else
6418                 {
6419                         // remove GLSL gamma texture
6420                 }
6421                 break;
6422         case RENDERPATH_GL13:
6423         case RENDERPATH_GL11:
6424                 break;
6425         }
6426 }
6427
6428 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6429 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6430 /*
6431 ================
6432 R_SelectScene
6433 ================
6434 */
6435 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6436         if( scenetype != r_currentscenetype ) {
6437                 // store the old scenetype
6438                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6439                 r_currentscenetype = scenetype;
6440                 // move in the new scene
6441                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6442         }
6443 }
6444
6445 /*
6446 ================
6447 R_GetScenePointer
6448 ================
6449 */
6450 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6451 {
6452         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6453         if( scenetype == r_currentscenetype ) {
6454                 return &r_refdef.scene;
6455         } else {
6456                 return &r_scenes_store[ scenetype ];
6457         }
6458 }
6459
6460 /*
6461 ================
6462 R_RenderView
6463 ================
6464 */
6465 int dpsoftrast_test;
6466 void R_RenderView(void)
6467 {
6468         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6469
6470         dpsoftrast_test = r_test.integer;
6471
6472         if (r_timereport_active)
6473                 R_TimeReport("start");
6474         r_textureframe++; // used only by R_GetCurrentTexture
6475         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6476
6477         if(R_CompileShader_CheckStaticParms())
6478                 R_GLSL_Restart_f();
6479
6480         if (!r_drawentities.integer)
6481                 r_refdef.scene.numentities = 0;
6482
6483         R_AnimCache_ClearCache();
6484         R_FrameData_NewFrame();
6485
6486         /* adjust for stereo display */
6487         if(R_Stereo_Active())
6488         {
6489                 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);
6490                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6491         }
6492
6493         if (r_refdef.view.isoverlay)
6494         {
6495                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6496                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6497                 R_TimeReport("depthclear");
6498
6499                 r_refdef.view.showdebug = false;
6500
6501                 r_waterstate.enabled = false;
6502                 r_waterstate.numwaterplanes = 0;
6503
6504                 R_RenderScene();
6505
6506                 r_refdef.view.matrix = originalmatrix;
6507
6508                 CHECKGLERROR
6509                 return;
6510         }
6511
6512         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6513         {
6514                 r_refdef.view.matrix = originalmatrix;
6515                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6516         }
6517
6518         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6519
6520         R_RenderView_UpdateViewVectors();
6521
6522         R_Shadow_UpdateWorldLightSelection();
6523
6524         R_Bloom_StartFrame();
6525         R_Water_StartFrame();
6526
6527         CHECKGLERROR
6528         if (r_timereport_active)
6529                 R_TimeReport("viewsetup");
6530
6531         R_ResetViewRendering3D();
6532
6533         if (r_refdef.view.clear || r_refdef.fogenabled)
6534         {
6535                 R_ClearScreen(r_refdef.fogenabled);
6536                 if (r_timereport_active)
6537                         R_TimeReport("viewclear");
6538         }
6539         r_refdef.view.clear = true;
6540
6541         // this produces a bloom texture to be used in R_BlendView() later
6542         if (r_hdr.integer && r_bloomstate.bloomwidth)
6543         {
6544                 R_HDR_RenderBloomTexture();
6545                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6546                 r_textureframe++; // used only by R_GetCurrentTexture
6547         }
6548
6549         r_refdef.view.showdebug = true;
6550
6551         R_View_Update();
6552         if (r_timereport_active)
6553                 R_TimeReport("visibility");
6554
6555         r_waterstate.numwaterplanes = 0;
6556         if (r_waterstate.enabled)
6557                 R_RenderWaterPlanes();
6558
6559         R_RenderScene();
6560         r_waterstate.numwaterplanes = 0;
6561
6562         R_BlendView();
6563         if (r_timereport_active)
6564                 R_TimeReport("blendview");
6565
6566         GL_Scissor(0, 0, vid.width, vid.height);
6567         GL_ScissorTest(false);
6568
6569         r_refdef.view.matrix = originalmatrix;
6570
6571         CHECKGLERROR
6572 }
6573
6574 void R_RenderWaterPlanes(void)
6575 {
6576         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6577         {
6578                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6579                 if (r_timereport_active)
6580                         R_TimeReport("waterworld");
6581         }
6582
6583         // don't let sound skip if going slow
6584         if (r_refdef.scene.extraupdate)
6585                 S_ExtraUpdate ();
6586
6587         R_DrawModelsAddWaterPlanes();
6588         if (r_timereport_active)
6589                 R_TimeReport("watermodels");
6590
6591         if (r_waterstate.numwaterplanes)
6592         {
6593                 R_Water_ProcessPlanes();
6594                 if (r_timereport_active)
6595                         R_TimeReport("waterscenes");
6596         }
6597 }
6598
6599 extern void R_DrawLightningBeams (void);
6600 extern void VM_CL_AddPolygonsToMeshQueue (void);
6601 extern void R_DrawPortals (void);
6602 extern cvar_t cl_locs_show;
6603 static void R_DrawLocs(void);
6604 static void R_DrawEntityBBoxes(void);
6605 static void R_DrawModelDecals(void);
6606 extern void R_DrawModelShadows(void);
6607 extern void R_DrawModelShadowMaps(void);
6608 extern cvar_t cl_decals_newsystem;
6609 extern qboolean r_shadow_usingdeferredprepass;
6610 void R_RenderScene(void)
6611 {
6612         qboolean shadowmapping = false;
6613
6614         if (r_timereport_active)
6615                 R_TimeReport("beginscene");
6616
6617         r_refdef.stats.renders++;
6618
6619         R_UpdateFogColor();
6620
6621         // don't let sound skip if going slow
6622         if (r_refdef.scene.extraupdate)
6623                 S_ExtraUpdate ();
6624
6625         R_MeshQueue_BeginScene();
6626
6627         R_SkyStartFrame();
6628
6629         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);
6630
6631         if (r_timereport_active)
6632                 R_TimeReport("skystartframe");
6633
6634         if (cl.csqc_vidvars.drawworld)
6635         {
6636                 // don't let sound skip if going slow
6637                 if (r_refdef.scene.extraupdate)
6638                         S_ExtraUpdate ();
6639
6640                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6641                 {
6642                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6643                         if (r_timereport_active)
6644                                 R_TimeReport("worldsky");
6645                 }
6646
6647                 if (R_DrawBrushModelsSky() && r_timereport_active)
6648                         R_TimeReport("bmodelsky");
6649
6650                 if (skyrendermasked && skyrenderlater)
6651                 {
6652                         // we have to force off the water clipping plane while rendering sky
6653                         R_SetupView(false);
6654                         R_Sky();
6655                         R_SetupView(true);
6656                         if (r_timereport_active)
6657                                 R_TimeReport("sky");
6658                 }
6659         }
6660
6661         R_AnimCache_CacheVisibleEntities();
6662         if (r_timereport_active)
6663                 R_TimeReport("animation");
6664
6665         R_Shadow_PrepareLights();
6666         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6667                 R_Shadow_PrepareModelShadows();
6668         if (r_timereport_active)
6669                 R_TimeReport("preparelights");
6670
6671         if (R_Shadow_ShadowMappingEnabled())
6672                 shadowmapping = true;
6673
6674         if (r_shadow_usingdeferredprepass)
6675                 R_Shadow_DrawPrepass();
6676
6677         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6678         {
6679                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6680                 if (r_timereport_active)
6681                         R_TimeReport("worlddepth");
6682         }
6683         if (r_depthfirst.integer >= 2)
6684         {
6685                 R_DrawModelsDepth();
6686                 if (r_timereport_active)
6687                         R_TimeReport("modeldepth");
6688         }
6689
6690         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6691         {
6692                 R_DrawModelShadowMaps();
6693                 R_ResetViewRendering3D();
6694                 // don't let sound skip if going slow
6695                 if (r_refdef.scene.extraupdate)
6696                         S_ExtraUpdate ();
6697         }
6698
6699         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6700         {
6701                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6702                 if (r_timereport_active)
6703                         R_TimeReport("world");
6704         }
6705
6706         // don't let sound skip if going slow
6707         if (r_refdef.scene.extraupdate)
6708                 S_ExtraUpdate ();
6709
6710         R_DrawModels();
6711         if (r_timereport_active)
6712                 R_TimeReport("models");
6713
6714         // don't let sound skip if going slow
6715         if (r_refdef.scene.extraupdate)
6716                 S_ExtraUpdate ();
6717
6718         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6719         {
6720                 R_DrawModelShadows();
6721                 R_ResetViewRendering3D();
6722                 // don't let sound skip if going slow
6723                 if (r_refdef.scene.extraupdate)
6724                         S_ExtraUpdate ();
6725         }
6726
6727         if (!r_shadow_usingdeferredprepass)
6728         {
6729                 R_Shadow_DrawLights();
6730                 if (r_timereport_active)
6731                         R_TimeReport("rtlights");
6732         }
6733
6734         // don't let sound skip if going slow
6735         if (r_refdef.scene.extraupdate)
6736                 S_ExtraUpdate ();
6737
6738         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6739         {
6740                 R_DrawModelShadows();
6741                 R_ResetViewRendering3D();
6742                 // don't let sound skip if going slow
6743                 if (r_refdef.scene.extraupdate)
6744                         S_ExtraUpdate ();
6745         }
6746
6747         if (cl.csqc_vidvars.drawworld)
6748         {
6749                 if (cl_decals_newsystem.integer)
6750                 {
6751                         R_DrawModelDecals();
6752                         if (r_timereport_active)
6753                                 R_TimeReport("modeldecals");
6754                 }
6755                 else
6756                 {
6757                         R_DrawDecals();
6758                         if (r_timereport_active)
6759                                 R_TimeReport("decals");
6760                 }
6761
6762                 R_DrawParticles();
6763                 if (r_timereport_active)
6764                         R_TimeReport("particles");
6765
6766                 R_DrawExplosions();
6767                 if (r_timereport_active)
6768                         R_TimeReport("explosions");
6769
6770                 R_DrawLightningBeams();
6771                 if (r_timereport_active)
6772                         R_TimeReport("lightning");
6773         }
6774
6775         VM_CL_AddPolygonsToMeshQueue();
6776
6777         if (r_refdef.view.showdebug)
6778         {
6779                 if (cl_locs_show.integer)
6780                 {
6781                         R_DrawLocs();
6782                         if (r_timereport_active)
6783                                 R_TimeReport("showlocs");
6784                 }
6785
6786                 if (r_drawportals.integer)
6787                 {
6788                         R_DrawPortals();
6789                         if (r_timereport_active)
6790                                 R_TimeReport("portals");
6791                 }
6792
6793                 if (r_showbboxes.value > 0)
6794                 {
6795                         R_DrawEntityBBoxes();
6796                         if (r_timereport_active)
6797                                 R_TimeReport("bboxes");
6798                 }
6799         }
6800
6801         R_MeshQueue_RenderTransparent();
6802         if (r_timereport_active)
6803                 R_TimeReport("drawtrans");
6804
6805         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))
6806         {
6807                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6808                 if (r_timereport_active)
6809                         R_TimeReport("worlddebug");
6810                 R_DrawModelsDebug();
6811                 if (r_timereport_active)
6812                         R_TimeReport("modeldebug");
6813         }
6814
6815         if (cl.csqc_vidvars.drawworld)
6816         {
6817                 R_Shadow_DrawCoronas();
6818                 if (r_timereport_active)
6819                         R_TimeReport("coronas");
6820         }
6821
6822 #if 0
6823         {
6824                 GL_DepthTest(false);
6825                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6826                 GL_Color(1, 1, 1, 1);
6827                 qglBegin(GL_POLYGON);
6828                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6829                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6830                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6831                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6832                 qglEnd();
6833                 qglBegin(GL_POLYGON);
6834                 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]);
6835                 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]);
6836                 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]);
6837                 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]);
6838                 qglEnd();
6839                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6840         }
6841 #endif
6842
6843         // don't let sound skip if going slow
6844         if (r_refdef.scene.extraupdate)
6845                 S_ExtraUpdate ();
6846
6847         R_ResetViewRendering2D();
6848 }
6849
6850 static const unsigned short bboxelements[36] =
6851 {
6852         5, 1, 3, 5, 3, 7,
6853         6, 2, 0, 6, 0, 4,
6854         7, 3, 2, 7, 2, 6,
6855         4, 0, 1, 4, 1, 5,
6856         4, 5, 7, 4, 7, 6,
6857         1, 0, 2, 1, 2, 3,
6858 };
6859
6860 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6861 {
6862         int i;
6863         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6864
6865         RSurf_ActiveWorldEntity();
6866
6867         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6868         GL_DepthMask(false);
6869         GL_DepthRange(0, 1);
6870         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6871 //      R_Mesh_ResetTextureState();
6872
6873         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6874         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6875         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6876         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6877         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6878         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6879         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6880         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6881         R_FillColors(color4f, 8, cr, cg, cb, ca);
6882         if (r_refdef.fogenabled)
6883         {
6884                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6885                 {
6886                         f1 = RSurf_FogVertex(v);
6887                         f2 = 1 - f1;
6888                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6889                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6890                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6891                 }
6892         }
6893         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6894         R_Mesh_ResetTextureState();
6895         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6896         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6897 }
6898
6899 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6900 {
6901         int i;
6902         float color[4];
6903         prvm_edict_t *edict;
6904         prvm_prog_t *prog_save = prog;
6905
6906         // this function draws bounding boxes of server entities
6907         if (!sv.active)
6908                 return;
6909
6910         GL_CullFace(GL_NONE);
6911         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6912
6913         prog = 0;
6914         SV_VM_Begin();
6915         for (i = 0;i < numsurfaces;i++)
6916         {
6917                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6918                 switch ((int)edict->fields.server->solid)
6919                 {
6920                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6921                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6922                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6923                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6924                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6925                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6926                 }
6927                 color[3] *= r_showbboxes.value;
6928                 color[3] = bound(0, color[3], 1);
6929                 GL_DepthTest(!r_showdisabledepthtest.integer);
6930                 GL_CullFace(r_refdef.view.cullface_front);
6931                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6932         }
6933         SV_VM_End();
6934         prog = prog_save;
6935 }
6936
6937 static void R_DrawEntityBBoxes(void)
6938 {
6939         int i;
6940         prvm_edict_t *edict;
6941         vec3_t center;
6942         prvm_prog_t *prog_save = prog;
6943
6944         // this function draws bounding boxes of server entities
6945         if (!sv.active)
6946                 return;
6947
6948         prog = 0;
6949         SV_VM_Begin();
6950         for (i = 0;i < prog->num_edicts;i++)
6951         {
6952                 edict = PRVM_EDICT_NUM(i);
6953                 if (edict->priv.server->free)
6954                         continue;
6955                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6956                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6957                         continue;
6958                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6959                         continue;
6960                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6961                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6962         }
6963         SV_VM_End();
6964         prog = prog_save;
6965 }
6966
6967 static const int nomodelelement3i[24] =
6968 {
6969         5, 2, 0,
6970         5, 1, 2,
6971         5, 0, 3,
6972         5, 3, 1,
6973         0, 2, 4,
6974         2, 1, 4,
6975         3, 0, 4,
6976         1, 3, 4
6977 };
6978
6979 static const unsigned short nomodelelement3s[24] =
6980 {
6981         5, 2, 0,
6982         5, 1, 2,
6983         5, 0, 3,
6984         5, 3, 1,
6985         0, 2, 4,
6986         2, 1, 4,
6987         3, 0, 4,
6988         1, 3, 4
6989 };
6990
6991 static const float nomodelvertex3f[6*3] =
6992 {
6993         -16,   0,   0,
6994          16,   0,   0,
6995           0, -16,   0,
6996           0,  16,   0,
6997           0,   0, -16,
6998           0,   0,  16
6999 };
7000
7001 static const float nomodelcolor4f[6*4] =
7002 {
7003         0.0f, 0.0f, 0.5f, 1.0f,
7004         0.0f, 0.0f, 0.5f, 1.0f,
7005         0.0f, 0.5f, 0.0f, 1.0f,
7006         0.0f, 0.5f, 0.0f, 1.0f,
7007         0.5f, 0.0f, 0.0f, 1.0f,
7008         0.5f, 0.0f, 0.0f, 1.0f
7009 };
7010
7011 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7012 {
7013         int i;
7014         float f1, f2, *c;
7015         float color4f[6*4];
7016
7017         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);
7018
7019         // this is only called once per entity so numsurfaces is always 1, and
7020         // surfacelist is always {0}, so this code does not handle batches
7021
7022         if (rsurface.ent_flags & RENDER_ADDITIVE)
7023         {
7024                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7025                 GL_DepthMask(false);
7026         }
7027         else if (rsurface.colormod[3] < 1)
7028         {
7029                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7030                 GL_DepthMask(false);
7031         }
7032         else
7033         {
7034                 GL_BlendFunc(GL_ONE, GL_ZERO);
7035                 GL_DepthMask(true);
7036         }
7037         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7038         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7039         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7040         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7041         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7042         for (i = 0, c = color4f;i < 6;i++, c += 4)
7043         {
7044                 c[0] *= rsurface.colormod[0];
7045                 c[1] *= rsurface.colormod[1];
7046                 c[2] *= rsurface.colormod[2];
7047                 c[3] *= rsurface.colormod[3];
7048         }
7049         if (r_refdef.fogenabled)
7050         {
7051                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7052                 {
7053                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7054                         f2 = 1 - f1;
7055                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7056                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7057                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7058                 }
7059         }
7060 //      R_Mesh_ResetTextureState();
7061         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7062         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7063         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7064 }
7065
7066 void R_DrawNoModel(entity_render_t *ent)
7067 {
7068         vec3_t org;
7069         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7070         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7071                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7072         else
7073                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7074 }
7075
7076 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7077 {
7078         vec3_t right1, right2, diff, normal;
7079
7080         VectorSubtract (org2, org1, normal);
7081
7082         // calculate 'right' vector for start
7083         VectorSubtract (r_refdef.view.origin, org1, diff);
7084         CrossProduct (normal, diff, right1);
7085         VectorNormalize (right1);
7086
7087         // calculate 'right' vector for end
7088         VectorSubtract (r_refdef.view.origin, org2, diff);
7089         CrossProduct (normal, diff, right2);
7090         VectorNormalize (right2);
7091
7092         vert[ 0] = org1[0] + width * right1[0];
7093         vert[ 1] = org1[1] + width * right1[1];
7094         vert[ 2] = org1[2] + width * right1[2];
7095         vert[ 3] = org1[0] - width * right1[0];
7096         vert[ 4] = org1[1] - width * right1[1];
7097         vert[ 5] = org1[2] - width * right1[2];
7098         vert[ 6] = org2[0] - width * right2[0];
7099         vert[ 7] = org2[1] - width * right2[1];
7100         vert[ 8] = org2[2] - width * right2[2];
7101         vert[ 9] = org2[0] + width * right2[0];
7102         vert[10] = org2[1] + width * right2[1];
7103         vert[11] = org2[2] + width * right2[2];
7104 }
7105
7106 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)
7107 {
7108         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7109         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7110         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7111         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7112         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7113         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7114         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7115         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7116         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7117         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7118         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7119         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7120 }
7121
7122 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7123 {
7124         int i;
7125         float *vertex3f;
7126         float v[3];
7127         VectorSet(v, x, y, z);
7128         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7129                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7130                         break;
7131         if (i == mesh->numvertices)
7132         {
7133                 if (mesh->numvertices < mesh->maxvertices)
7134                 {
7135                         VectorCopy(v, vertex3f);
7136                         mesh->numvertices++;
7137                 }
7138                 return mesh->numvertices;
7139         }
7140         else
7141                 return i;
7142 }
7143
7144 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7145 {
7146         int i;
7147         int *e, element[3];
7148         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7149         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7150         e = mesh->element3i + mesh->numtriangles * 3;
7151         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7152         {
7153                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7154                 if (mesh->numtriangles < mesh->maxtriangles)
7155                 {
7156                         *e++ = element[0];
7157                         *e++ = element[1];
7158                         *e++ = element[2];
7159                         mesh->numtriangles++;
7160                 }
7161                 element[1] = element[2];
7162         }
7163 }
7164
7165 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7166 {
7167         int i;
7168         int *e, element[3];
7169         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7170         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7171         e = mesh->element3i + mesh->numtriangles * 3;
7172         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7173         {
7174                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7175                 if (mesh->numtriangles < mesh->maxtriangles)
7176                 {
7177                         *e++ = element[0];
7178                         *e++ = element[1];
7179                         *e++ = element[2];
7180                         mesh->numtriangles++;
7181                 }
7182                 element[1] = element[2];
7183         }
7184 }
7185
7186 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7187 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7188 {
7189         int planenum, planenum2;
7190         int w;
7191         int tempnumpoints;
7192         mplane_t *plane, *plane2;
7193         double maxdist;
7194         double temppoints[2][256*3];
7195         // figure out how large a bounding box we need to properly compute this brush
7196         maxdist = 0;
7197         for (w = 0;w < numplanes;w++)
7198                 maxdist = max(maxdist, fabs(planes[w].dist));
7199         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7200         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7201         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7202         {
7203                 w = 0;
7204                 tempnumpoints = 4;
7205                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7206                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7207                 {
7208                         if (planenum2 == planenum)
7209                                 continue;
7210                         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);
7211                         w = !w;
7212                 }
7213                 if (tempnumpoints < 3)
7214                         continue;
7215                 // generate elements forming a triangle fan for this polygon
7216                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7217         }
7218 }
7219
7220 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)
7221 {
7222         texturelayer_t *layer;
7223         layer = t->currentlayers + t->currentnumlayers++;
7224         layer->type = type;
7225         layer->depthmask = depthmask;
7226         layer->blendfunc1 = blendfunc1;
7227         layer->blendfunc2 = blendfunc2;
7228         layer->texture = texture;
7229         layer->texmatrix = *matrix;
7230         layer->color[0] = r;
7231         layer->color[1] = g;
7232         layer->color[2] = b;
7233         layer->color[3] = a;
7234 }
7235
7236 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7237 {
7238         if(parms[0] == 0 && parms[1] == 0)
7239                 return false;
7240         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7241                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7242                         return false;
7243         return true;
7244 }
7245
7246 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7247 {
7248         double index, f;
7249         index = parms[2] + r_refdef.scene.time * parms[3];
7250         index -= floor(index);
7251         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7252         {
7253         default:
7254         case Q3WAVEFUNC_NONE:
7255         case Q3WAVEFUNC_NOISE:
7256         case Q3WAVEFUNC_COUNT:
7257                 f = 0;
7258                 break;
7259         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7260         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7261         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7262         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7263         case Q3WAVEFUNC_TRIANGLE:
7264                 index *= 4;
7265                 f = index - floor(index);
7266                 if (index < 1)
7267                         f = f;
7268                 else if (index < 2)
7269                         f = 1 - f;
7270                 else if (index < 3)
7271                         f = -f;
7272                 else
7273                         f = -(1 - f);
7274                 break;
7275         }
7276         f = parms[0] + parms[1] * f;
7277         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7278                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7279         return (float) f;
7280 }
7281
7282 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7283 {
7284         int w, h, idx;
7285         float f;
7286         float tcmat[12];
7287         matrix4x4_t matrix, temp;
7288         switch(tcmod->tcmod)
7289         {
7290                 case Q3TCMOD_COUNT:
7291                 case Q3TCMOD_NONE:
7292                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7293                                 matrix = r_waterscrollmatrix;
7294                         else
7295                                 matrix = identitymatrix;
7296                         break;
7297                 case Q3TCMOD_ENTITYTRANSLATE:
7298                         // this is used in Q3 to allow the gamecode to control texcoord
7299                         // scrolling on the entity, which is not supported in darkplaces yet.
7300                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7301                         break;
7302                 case Q3TCMOD_ROTATE:
7303                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7304                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7305                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7306                         break;
7307                 case Q3TCMOD_SCALE:
7308                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7309                         break;
7310                 case Q3TCMOD_SCROLL:
7311                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7312                         break;
7313                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7314                         w = (int) tcmod->parms[0];
7315                         h = (int) tcmod->parms[1];
7316                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7317                         f = f - floor(f);
7318                         idx = (int) floor(f * w * h);
7319                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7320                         break;
7321                 case Q3TCMOD_STRETCH:
7322                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7323                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7324                         break;
7325                 case Q3TCMOD_TRANSFORM:
7326                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7327                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7328                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7329                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7330                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7331                         break;
7332                 case Q3TCMOD_TURBULENT:
7333                         // this is handled in the RSurf_PrepareVertices function
7334                         matrix = identitymatrix;
7335                         break;
7336         }
7337         temp = *texmatrix;
7338         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7339 }
7340
7341 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7342 {
7343         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7344         char name[MAX_QPATH];
7345         skinframe_t *skinframe;
7346         unsigned char pixels[296*194];
7347         strlcpy(cache->name, skinname, sizeof(cache->name));
7348         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7349         if (developer_loading.integer)
7350                 Con_Printf("loading %s\n", name);
7351         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7352         if (!skinframe || !skinframe->base)
7353         {
7354                 unsigned char *f;
7355                 fs_offset_t filesize;
7356                 skinframe = NULL;
7357                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7358                 if (f)
7359                 {
7360                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7361                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7362                         Mem_Free(f);
7363                 }
7364         }
7365         cache->skinframe = skinframe;
7366 }
7367
7368 texture_t *R_GetCurrentTexture(texture_t *t)
7369 {
7370         int i;
7371         const entity_render_t *ent = rsurface.entity;
7372         dp_model_t *model = ent->model;
7373         q3shaderinfo_layer_tcmod_t *tcmod;
7374
7375         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7376                 return t->currentframe;
7377         t->update_lastrenderframe = r_textureframe;
7378         t->update_lastrenderentity = (void *)ent;
7379
7380         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7381                 t->camera_entity = ent->entitynumber;
7382         else
7383                 t->camera_entity = 0;
7384
7385         // switch to an alternate material if this is a q1bsp animated material
7386         {
7387                 texture_t *texture = t;
7388                 int s = rsurface.ent_skinnum;
7389                 if ((unsigned int)s >= (unsigned int)model->numskins)
7390                         s = 0;
7391                 if (model->skinscenes)
7392                 {
7393                         if (model->skinscenes[s].framecount > 1)
7394                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7395                         else
7396                                 s = model->skinscenes[s].firstframe;
7397                 }
7398                 if (s > 0)
7399                         t = t + s * model->num_surfaces;
7400                 if (t->animated)
7401                 {
7402                         // use an alternate animation if the entity's frame is not 0,
7403                         // and only if the texture has an alternate animation
7404                         if (rsurface.ent_alttextures && t->anim_total[1])
7405                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7406                         else
7407                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7408                 }
7409                 texture->currentframe = t;
7410         }
7411
7412         // update currentskinframe to be a qw skin or animation frame
7413         if (rsurface.ent_qwskin >= 0)
7414         {
7415                 i = rsurface.ent_qwskin;
7416                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7417                 {
7418                         r_qwskincache_size = cl.maxclients;
7419                         if (r_qwskincache)
7420                                 Mem_Free(r_qwskincache);
7421                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7422                 }
7423                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7424                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7425                 t->currentskinframe = r_qwskincache[i].skinframe;
7426                 if (t->currentskinframe == NULL)
7427                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7428         }
7429         else if (t->numskinframes >= 2)
7430                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7431         if (t->backgroundnumskinframes >= 2)
7432                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7433
7434         t->currentmaterialflags = t->basematerialflags;
7435         t->currentalpha = rsurface.colormod[3];
7436         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7437                 t->currentalpha *= r_wateralpha.value;
7438         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7439                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7440         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7441                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7442         if (!(rsurface.ent_flags & RENDER_LIGHT))
7443                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7444         else if (FAKELIGHT_ENABLED)
7445         {
7446                         // no modellight if using fakelight for the map
7447         }
7448         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7449         {
7450                 // pick a model lighting mode
7451                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7452                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7453                 else
7454                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7455         }
7456         if (rsurface.ent_flags & RENDER_ADDITIVE)
7457                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7458         else if (t->currentalpha < 1)
7459                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7460         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7461                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7462         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7463                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7464         if (t->backgroundnumskinframes)
7465                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7466         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7467         {
7468                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7469                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7470         }
7471         else
7472                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7473         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7474                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7475
7476         // there is no tcmod
7477         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7478         {
7479                 t->currenttexmatrix = r_waterscrollmatrix;
7480                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7481         }
7482         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7483         {
7484                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7485                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7486         }
7487
7488         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7489                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7490         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7491                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7492
7493         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7494         if (t->currentskinframe->qpixels)
7495                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7496         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7497         if (!t->basetexture)
7498                 t->basetexture = r_texture_notexture;
7499         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7500         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7501         t->nmaptexture = t->currentskinframe->nmap;
7502         if (!t->nmaptexture)
7503                 t->nmaptexture = r_texture_blanknormalmap;
7504         t->glosstexture = r_texture_black;
7505         t->glowtexture = t->currentskinframe->glow;
7506         t->fogtexture = t->currentskinframe->fog;
7507         t->reflectmasktexture = t->currentskinframe->reflect;
7508         if (t->backgroundnumskinframes)
7509         {
7510                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7511                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7512                 t->backgroundglosstexture = r_texture_black;
7513                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7514                 if (!t->backgroundnmaptexture)
7515                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7516         }
7517         else
7518         {
7519                 t->backgroundbasetexture = r_texture_white;
7520                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7521                 t->backgroundglosstexture = r_texture_black;
7522                 t->backgroundglowtexture = NULL;
7523         }
7524         t->specularpower = r_shadow_glossexponent.value;
7525         // TODO: store reference values for these in the texture?
7526         t->specularscale = 0;
7527         if (r_shadow_gloss.integer > 0)
7528         {
7529                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7530                 {
7531                         if (r_shadow_glossintensity.value > 0)
7532                         {
7533                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7534                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7535                                 t->specularscale = r_shadow_glossintensity.value;
7536                         }
7537                 }
7538                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7539                 {
7540                         t->glosstexture = r_texture_white;
7541                         t->backgroundglosstexture = r_texture_white;
7542                         t->specularscale = r_shadow_gloss2intensity.value;
7543                         t->specularpower = r_shadow_gloss2exponent.value;
7544                 }
7545         }
7546         t->specularscale *= t->specularscalemod;
7547         t->specularpower *= t->specularpowermod;
7548
7549         // lightmaps mode looks bad with dlights using actual texturing, so turn
7550         // off the colormap and glossmap, but leave the normalmap on as it still
7551         // accurately represents the shading involved
7552         if (gl_lightmaps.integer)
7553         {
7554                 t->basetexture = r_texture_grey128;
7555                 t->pantstexture = r_texture_black;
7556                 t->shirttexture = r_texture_black;
7557                 t->nmaptexture = r_texture_blanknormalmap;
7558                 t->glosstexture = r_texture_black;
7559                 t->glowtexture = NULL;
7560                 t->fogtexture = NULL;
7561                 t->reflectmasktexture = NULL;
7562                 t->backgroundbasetexture = NULL;
7563                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7564                 t->backgroundglosstexture = r_texture_black;
7565                 t->backgroundglowtexture = NULL;
7566                 t->specularscale = 0;
7567                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7568         }
7569
7570         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7571         VectorClear(t->dlightcolor);
7572         t->currentnumlayers = 0;
7573         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7574         {
7575                 int blendfunc1, blendfunc2;
7576                 qboolean depthmask;
7577                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7578                 {
7579                         blendfunc1 = GL_SRC_ALPHA;
7580                         blendfunc2 = GL_ONE;
7581                 }
7582                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7583                 {
7584                         blendfunc1 = GL_SRC_ALPHA;
7585                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7586                 }
7587                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7588                 {
7589                         blendfunc1 = t->customblendfunc[0];
7590                         blendfunc2 = t->customblendfunc[1];
7591                 }
7592                 else
7593                 {
7594                         blendfunc1 = GL_ONE;
7595                         blendfunc2 = GL_ZERO;
7596                 }
7597                 // don't colormod evilblend textures
7598                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7599                         VectorSet(t->lightmapcolor, 1, 1, 1);
7600                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7601                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7602                 {
7603                         // fullbright is not affected by r_refdef.lightmapintensity
7604                         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]);
7605                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7606                                 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]);
7607                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7608                                 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]);
7609                 }
7610                 else
7611                 {
7612                         vec3_t ambientcolor;
7613                         float colorscale;
7614                         // set the color tint used for lights affecting this surface
7615                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7616                         colorscale = 2;
7617                         // q3bsp has no lightmap updates, so the lightstylevalue that
7618                         // would normally be baked into the lightmap must be
7619                         // applied to the color
7620                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7621                         if (model->type == mod_brushq3)
7622                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7623                         colorscale *= r_refdef.lightmapintensity;
7624                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7625                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7626                         // basic lit geometry
7627                         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]);
7628                         // add pants/shirt if needed
7629                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7630                                 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]);
7631                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7632                                 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]);
7633                         // now add ambient passes if needed
7634                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7635                         {
7636                                 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]);
7637                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7638                                         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]);
7639                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7640                                         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]);
7641                         }
7642                 }
7643                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7644                         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]);
7645                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7646                 {
7647                         // if this is opaque use alpha blend which will darken the earlier
7648                         // passes cheaply.
7649                         //
7650                         // if this is an alpha blended material, all the earlier passes
7651                         // were darkened by fog already, so we only need to add the fog
7652                         // color ontop through the fog mask texture
7653                         //
7654                         // if this is an additive blended material, all the earlier passes
7655                         // were darkened by fog already, and we should not add fog color
7656                         // (because the background was not darkened, there is no fog color
7657                         // that was lost behind it).
7658                         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]);
7659                 }
7660         }
7661
7662         return t->currentframe;
7663 }
7664
7665 rsurfacestate_t rsurface;
7666
7667 void RSurf_ActiveWorldEntity(void)
7668 {
7669         dp_model_t *model = r_refdef.scene.worldmodel;
7670         //if (rsurface.entity == r_refdef.scene.worldentity)
7671         //      return;
7672         rsurface.entity = r_refdef.scene.worldentity;
7673         rsurface.skeleton = NULL;
7674         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7675         rsurface.ent_skinnum = 0;
7676         rsurface.ent_qwskin = -1;
7677         rsurface.ent_shadertime = 0;
7678         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7679         rsurface.matrix = identitymatrix;
7680         rsurface.inversematrix = identitymatrix;
7681         rsurface.matrixscale = 1;
7682         rsurface.inversematrixscale = 1;
7683         R_EntityMatrix(&identitymatrix);
7684         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7685         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7686         rsurface.fograngerecip = r_refdef.fograngerecip;
7687         rsurface.fogheightfade = r_refdef.fogheightfade;
7688         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7689         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7690         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7691         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7692         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7693         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7694         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7695         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7696         rsurface.colormod[3] = 1;
7697         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);
7698         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7699         rsurface.frameblend[0].lerp = 1;
7700         rsurface.ent_alttextures = false;
7701         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7702         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7703         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7704         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7705         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7706         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7707         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7708         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7709         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7710         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7711         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7712         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7713         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7714         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7715         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7716         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7717         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7718         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7719         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7720         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7721         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7722         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7723         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7724         rsurface.modelelement3i = model->surfmesh.data_element3i;
7725         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7726         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7727         rsurface.modelelement3s = model->surfmesh.data_element3s;
7728         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7729         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7730         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7731         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7732         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7733         rsurface.modelsurfaces = model->data_surfaces;
7734         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7735         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7736         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7737         rsurface.modelgeneratedvertex = false;
7738         rsurface.batchgeneratedvertex = false;
7739         rsurface.batchfirstvertex = 0;
7740         rsurface.batchnumvertices = 0;
7741         rsurface.batchfirsttriangle = 0;
7742         rsurface.batchnumtriangles = 0;
7743         rsurface.batchvertex3f  = NULL;
7744         rsurface.batchvertex3f_vertexbuffer = NULL;
7745         rsurface.batchvertex3f_bufferoffset = 0;
7746         rsurface.batchsvector3f = NULL;
7747         rsurface.batchsvector3f_vertexbuffer = NULL;
7748         rsurface.batchsvector3f_bufferoffset = 0;
7749         rsurface.batchtvector3f = NULL;
7750         rsurface.batchtvector3f_vertexbuffer = NULL;
7751         rsurface.batchtvector3f_bufferoffset = 0;
7752         rsurface.batchnormal3f  = NULL;
7753         rsurface.batchnormal3f_vertexbuffer = NULL;
7754         rsurface.batchnormal3f_bufferoffset = 0;
7755         rsurface.batchlightmapcolor4f = NULL;
7756         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7757         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7758         rsurface.batchtexcoordtexture2f = NULL;
7759         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7760         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7761         rsurface.batchtexcoordlightmap2f = NULL;
7762         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7763         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7764         rsurface.batchvertexmesh = NULL;
7765         rsurface.batchvertexmeshbuffer = NULL;
7766         rsurface.batchvertex3fbuffer = NULL;
7767         rsurface.batchelement3i = NULL;
7768         rsurface.batchelement3i_indexbuffer = NULL;
7769         rsurface.batchelement3i_bufferoffset = 0;
7770         rsurface.batchelement3s = NULL;
7771         rsurface.batchelement3s_indexbuffer = NULL;
7772         rsurface.batchelement3s_bufferoffset = 0;
7773         rsurface.passcolor4f = NULL;
7774         rsurface.passcolor4f_vertexbuffer = NULL;
7775         rsurface.passcolor4f_bufferoffset = 0;
7776 }
7777
7778 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7779 {
7780         dp_model_t *model = ent->model;
7781         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7782         //      return;
7783         rsurface.entity = (entity_render_t *)ent;
7784         rsurface.skeleton = ent->skeleton;
7785         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7786         rsurface.ent_skinnum = ent->skinnum;
7787         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;
7788         rsurface.ent_shadertime = ent->shadertime;
7789         rsurface.ent_flags = ent->flags;
7790         rsurface.matrix = ent->matrix;
7791         rsurface.inversematrix = ent->inversematrix;
7792         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7793         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7794         R_EntityMatrix(&rsurface.matrix);
7795         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7796         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7797         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7798         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7799         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7800         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7801         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7802         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7803         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7804         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7805         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7806         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7807         rsurface.colormod[3] = ent->alpha;
7808         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7809         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7810         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7811         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7812         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7813         if (ent->model->brush.submodel && !prepass)
7814         {
7815                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7816                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7817         }
7818         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7819         {
7820                 if (ent->animcache_vertex3f)
7821                 {
7822                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7823                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7824                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7825                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7826                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7827                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7828                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7829                 }
7830                 else if (wanttangents)
7831                 {
7832                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7833                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7834                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7835                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7836                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7837                         rsurface.modelvertexmesh = NULL;
7838                         rsurface.modelvertexmeshbuffer = NULL;
7839                         rsurface.modelvertex3fbuffer = NULL;
7840                 }
7841                 else if (wantnormals)
7842                 {
7843                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7844                         rsurface.modelsvector3f = NULL;
7845                         rsurface.modeltvector3f = NULL;
7846                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7847                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7848                         rsurface.modelvertexmesh = NULL;
7849                         rsurface.modelvertexmeshbuffer = NULL;
7850                         rsurface.modelvertex3fbuffer = NULL;
7851                 }
7852                 else
7853                 {
7854                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7855                         rsurface.modelsvector3f = NULL;
7856                         rsurface.modeltvector3f = NULL;
7857                         rsurface.modelnormal3f = NULL;
7858                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7859                         rsurface.modelvertexmesh = NULL;
7860                         rsurface.modelvertexmeshbuffer = NULL;
7861                         rsurface.modelvertex3fbuffer = NULL;
7862                 }
7863                 rsurface.modelvertex3f_vertexbuffer = 0;
7864                 rsurface.modelvertex3f_bufferoffset = 0;
7865                 rsurface.modelsvector3f_vertexbuffer = 0;
7866                 rsurface.modelsvector3f_bufferoffset = 0;
7867                 rsurface.modeltvector3f_vertexbuffer = 0;
7868                 rsurface.modeltvector3f_bufferoffset = 0;
7869                 rsurface.modelnormal3f_vertexbuffer = 0;
7870                 rsurface.modelnormal3f_bufferoffset = 0;
7871                 rsurface.modelgeneratedvertex = true;
7872         }
7873         else
7874         {
7875                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7876                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7877                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7878                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7879                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7880                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7881                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7882                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7883                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7884                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7885                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7886                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7887                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7888                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7889                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7890                 rsurface.modelgeneratedvertex = false;
7891         }
7892         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7893         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7894         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7895         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7896         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7897         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7898         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7899         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7900         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7901         rsurface.modelelement3i = model->surfmesh.data_element3i;
7902         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7903         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7904         rsurface.modelelement3s = model->surfmesh.data_element3s;
7905         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7906         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7907         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7908         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7909         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7910         rsurface.modelsurfaces = model->data_surfaces;
7911         rsurface.batchgeneratedvertex = false;
7912         rsurface.batchfirstvertex = 0;
7913         rsurface.batchnumvertices = 0;
7914         rsurface.batchfirsttriangle = 0;
7915         rsurface.batchnumtriangles = 0;
7916         rsurface.batchvertex3f  = NULL;
7917         rsurface.batchvertex3f_vertexbuffer = NULL;
7918         rsurface.batchvertex3f_bufferoffset = 0;
7919         rsurface.batchsvector3f = NULL;
7920         rsurface.batchsvector3f_vertexbuffer = NULL;
7921         rsurface.batchsvector3f_bufferoffset = 0;
7922         rsurface.batchtvector3f = NULL;
7923         rsurface.batchtvector3f_vertexbuffer = NULL;
7924         rsurface.batchtvector3f_bufferoffset = 0;
7925         rsurface.batchnormal3f  = NULL;
7926         rsurface.batchnormal3f_vertexbuffer = NULL;
7927         rsurface.batchnormal3f_bufferoffset = 0;
7928         rsurface.batchlightmapcolor4f = NULL;
7929         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7930         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7931         rsurface.batchtexcoordtexture2f = NULL;
7932         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7933         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7934         rsurface.batchtexcoordlightmap2f = NULL;
7935         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7936         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7937         rsurface.batchvertexmesh = NULL;
7938         rsurface.batchvertexmeshbuffer = NULL;
7939         rsurface.batchvertex3fbuffer = NULL;
7940         rsurface.batchelement3i = NULL;
7941         rsurface.batchelement3i_indexbuffer = NULL;
7942         rsurface.batchelement3i_bufferoffset = 0;
7943         rsurface.batchelement3s = NULL;
7944         rsurface.batchelement3s_indexbuffer = NULL;
7945         rsurface.batchelement3s_bufferoffset = 0;
7946         rsurface.passcolor4f = NULL;
7947         rsurface.passcolor4f_vertexbuffer = NULL;
7948         rsurface.passcolor4f_bufferoffset = 0;
7949 }
7950
7951 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)
7952 {
7953         rsurface.entity = r_refdef.scene.worldentity;
7954         rsurface.skeleton = NULL;
7955         rsurface.ent_skinnum = 0;
7956         rsurface.ent_qwskin = -1;
7957         rsurface.ent_shadertime = shadertime;
7958         rsurface.ent_flags = entflags;
7959         rsurface.modelnumvertices = numvertices;
7960         rsurface.modelnumtriangles = numtriangles;
7961         rsurface.matrix = *matrix;
7962         rsurface.inversematrix = *inversematrix;
7963         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7964         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7965         R_EntityMatrix(&rsurface.matrix);
7966         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7967         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7968         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7969         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7970         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7971         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7972         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7973         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7974         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7975         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7976         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7977         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7978         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);
7979         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7980         rsurface.frameblend[0].lerp = 1;
7981         rsurface.ent_alttextures = false;
7982         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7983         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7984         if (wanttangents)
7985         {
7986                 rsurface.modelvertex3f = (float *)vertex3f;
7987                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7988                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7989                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7990         }
7991         else if (wantnormals)
7992         {
7993                 rsurface.modelvertex3f = (float *)vertex3f;
7994                 rsurface.modelsvector3f = NULL;
7995                 rsurface.modeltvector3f = NULL;
7996                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7997         }
7998         else
7999         {
8000                 rsurface.modelvertex3f = (float *)vertex3f;
8001                 rsurface.modelsvector3f = NULL;
8002                 rsurface.modeltvector3f = NULL;
8003                 rsurface.modelnormal3f = NULL;
8004         }
8005         rsurface.modelvertexmesh = NULL;
8006         rsurface.modelvertexmeshbuffer = NULL;
8007         rsurface.modelvertex3fbuffer = NULL;
8008         rsurface.modelvertex3f_vertexbuffer = 0;
8009         rsurface.modelvertex3f_bufferoffset = 0;
8010         rsurface.modelsvector3f_vertexbuffer = 0;
8011         rsurface.modelsvector3f_bufferoffset = 0;
8012         rsurface.modeltvector3f_vertexbuffer = 0;
8013         rsurface.modeltvector3f_bufferoffset = 0;
8014         rsurface.modelnormal3f_vertexbuffer = 0;
8015         rsurface.modelnormal3f_bufferoffset = 0;
8016         rsurface.modelgeneratedvertex = true;
8017         rsurface.modellightmapcolor4f  = (float *)color4f;
8018         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8019         rsurface.modellightmapcolor4f_bufferoffset = 0;
8020         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8021         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8022         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8023         rsurface.modeltexcoordlightmap2f  = NULL;
8024         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8025         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8026         rsurface.modelelement3i = (int *)element3i;
8027         rsurface.modelelement3i_indexbuffer = NULL;
8028         rsurface.modelelement3i_bufferoffset = 0;
8029         rsurface.modelelement3s = (unsigned short *)element3s;
8030         rsurface.modelelement3s_indexbuffer = NULL;
8031         rsurface.modelelement3s_bufferoffset = 0;
8032         rsurface.modellightmapoffsets = NULL;
8033         rsurface.modelsurfaces = NULL;
8034         rsurface.batchgeneratedvertex = false;
8035         rsurface.batchfirstvertex = 0;
8036         rsurface.batchnumvertices = 0;
8037         rsurface.batchfirsttriangle = 0;
8038         rsurface.batchnumtriangles = 0;
8039         rsurface.batchvertex3f  = NULL;
8040         rsurface.batchvertex3f_vertexbuffer = NULL;
8041         rsurface.batchvertex3f_bufferoffset = 0;
8042         rsurface.batchsvector3f = NULL;
8043         rsurface.batchsvector3f_vertexbuffer = NULL;
8044         rsurface.batchsvector3f_bufferoffset = 0;
8045         rsurface.batchtvector3f = NULL;
8046         rsurface.batchtvector3f_vertexbuffer = NULL;
8047         rsurface.batchtvector3f_bufferoffset = 0;
8048         rsurface.batchnormal3f  = NULL;
8049         rsurface.batchnormal3f_vertexbuffer = NULL;
8050         rsurface.batchnormal3f_bufferoffset = 0;
8051         rsurface.batchlightmapcolor4f = NULL;
8052         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8053         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8054         rsurface.batchtexcoordtexture2f = NULL;
8055         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8056         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8057         rsurface.batchtexcoordlightmap2f = NULL;
8058         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8059         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8060         rsurface.batchvertexmesh = NULL;
8061         rsurface.batchvertexmeshbuffer = NULL;
8062         rsurface.batchvertex3fbuffer = NULL;
8063         rsurface.batchelement3i = NULL;
8064         rsurface.batchelement3i_indexbuffer = NULL;
8065         rsurface.batchelement3i_bufferoffset = 0;
8066         rsurface.batchelement3s = NULL;
8067         rsurface.batchelement3s_indexbuffer = NULL;
8068         rsurface.batchelement3s_bufferoffset = 0;
8069         rsurface.passcolor4f = NULL;
8070         rsurface.passcolor4f_vertexbuffer = NULL;
8071         rsurface.passcolor4f_bufferoffset = 0;
8072
8073         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8074         {
8075                 if ((wantnormals || wanttangents) && !normal3f)
8076                 {
8077                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8078                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8079                 }
8080                 if (wanttangents && !svector3f)
8081                 {
8082                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8083                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8084                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8085                 }
8086         }
8087 }
8088
8089 float RSurf_FogPoint(const float *v)
8090 {
8091         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8092         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8093         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8094         float FogHeightFade = r_refdef.fogheightfade;
8095         float fogfrac;
8096         unsigned int fogmasktableindex;
8097         if (r_refdef.fogplaneviewabove)
8098                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8099         else
8100                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8101         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8102         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8103 }
8104
8105 float RSurf_FogVertex(const float *v)
8106 {
8107         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8108         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8109         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8110         float FogHeightFade = rsurface.fogheightfade;
8111         float fogfrac;
8112         unsigned int fogmasktableindex;
8113         if (r_refdef.fogplaneviewabove)
8114                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8115         else
8116                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8117         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8118         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8119 }
8120
8121 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8122 {
8123         int i;
8124         for (i = 0;i < numelements;i++)
8125                 outelement3i[i] = inelement3i[i] + adjust;
8126 }
8127
8128 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8129 extern cvar_t gl_vbo;
8130 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8131 {
8132         int deformindex;
8133         int firsttriangle;
8134         int numtriangles;
8135         int firstvertex;
8136         int endvertex;
8137         int numvertices;
8138         int surfacefirsttriangle;
8139         int surfacenumtriangles;
8140         int surfacefirstvertex;
8141         int surfaceendvertex;
8142         int surfacenumvertices;
8143         int batchnumvertices;
8144         int batchnumtriangles;
8145         int needsupdate;
8146         int i, j;
8147         qboolean gaps;
8148         qboolean dynamicvertex;
8149         float amplitude;
8150         float animpos;
8151         float scale;
8152         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8153         float waveparms[4];
8154         q3shaderinfo_deform_t *deform;
8155         const msurface_t *surface, *firstsurface;
8156         r_vertexmesh_t *vertexmesh;
8157         if (!texturenumsurfaces)
8158                 return;
8159         // find vertex range of this surface batch
8160         gaps = false;
8161         firstsurface = texturesurfacelist[0];
8162         firsttriangle = firstsurface->num_firsttriangle;
8163         batchnumvertices = 0;
8164         batchnumtriangles = 0;
8165         firstvertex = endvertex = firstsurface->num_firstvertex;
8166         for (i = 0;i < texturenumsurfaces;i++)
8167         {
8168                 surface = texturesurfacelist[i];
8169                 if (surface != firstsurface + i)
8170                         gaps = true;
8171                 surfacefirstvertex = surface->num_firstvertex;
8172                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8173                 surfacenumvertices = surface->num_vertices;
8174                 surfacenumtriangles = surface->num_triangles;
8175                 if (firstvertex > surfacefirstvertex)
8176                         firstvertex = surfacefirstvertex;
8177                 if (endvertex < surfaceendvertex)
8178                         endvertex = surfaceendvertex;
8179                 batchnumvertices += surfacenumvertices;
8180                 batchnumtriangles += surfacenumtriangles;
8181         }
8182
8183         // we now know the vertex range used, and if there are any gaps in it
8184         rsurface.batchfirstvertex = firstvertex;
8185         rsurface.batchnumvertices = endvertex - firstvertex;
8186         rsurface.batchfirsttriangle = firsttriangle;
8187         rsurface.batchnumtriangles = batchnumtriangles;
8188
8189         // this variable holds flags for which properties have been updated that
8190         // may require regenerating vertexmesh array...
8191         needsupdate = 0;
8192
8193         // check if any dynamic vertex processing must occur
8194         dynamicvertex = false;
8195
8196         // if there is a chance of animated vertex colors, it's a dynamic batch
8197         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8198         {
8199                 dynamicvertex = true;
8200                 batchneed |= BATCHNEED_NOGAPS;
8201                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8202         }
8203
8204         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8205         {
8206                 switch (deform->deform)
8207                 {
8208                 default:
8209                 case Q3DEFORM_PROJECTIONSHADOW:
8210                 case Q3DEFORM_TEXT0:
8211                 case Q3DEFORM_TEXT1:
8212                 case Q3DEFORM_TEXT2:
8213                 case Q3DEFORM_TEXT3:
8214                 case Q3DEFORM_TEXT4:
8215                 case Q3DEFORM_TEXT5:
8216                 case Q3DEFORM_TEXT6:
8217                 case Q3DEFORM_TEXT7:
8218                 case Q3DEFORM_NONE:
8219                         break;
8220                 case Q3DEFORM_AUTOSPRITE:
8221                         dynamicvertex = true;
8222                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8223                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8224                         break;
8225                 case Q3DEFORM_AUTOSPRITE2:
8226                         dynamicvertex = true;
8227                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8228                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8229                         break;
8230                 case Q3DEFORM_NORMAL:
8231                         dynamicvertex = true;
8232                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8233                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8234                         break;
8235                 case Q3DEFORM_WAVE:
8236                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8237                                 break; // if wavefunc is a nop, ignore this transform
8238                         dynamicvertex = true;
8239                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8240                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8241                         break;
8242                 case Q3DEFORM_BULGE:
8243                         dynamicvertex = true;
8244                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8245                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8246                         break;
8247                 case Q3DEFORM_MOVE:
8248                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8249                                 break; // if wavefunc is a nop, ignore this transform
8250                         dynamicvertex = true;
8251                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8252                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8253                         break;
8254                 }
8255         }
8256         switch(rsurface.texture->tcgen.tcgen)
8257         {
8258         default:
8259         case Q3TCGEN_TEXTURE:
8260                 break;
8261         case Q3TCGEN_LIGHTMAP:
8262                 dynamicvertex = true;
8263                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8264                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8265                 break;
8266         case Q3TCGEN_VECTOR:
8267                 dynamicvertex = true;
8268                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8269                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8270                 break;
8271         case Q3TCGEN_ENVIRONMENT:
8272                 dynamicvertex = true;
8273                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8274                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8275                 break;
8276         }
8277         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8278         {
8279                 dynamicvertex = true;
8280                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8281                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8282         }
8283
8284         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8285         {
8286                 dynamicvertex = true;
8287                 batchneed |= BATCHNEED_NOGAPS;
8288                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8289         }
8290
8291         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8292         {
8293                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8294                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8295                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8296                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8297                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8298                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8299                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8300         }
8301
8302         // when the model data has no vertex buffer (dynamic mesh), we need to
8303         // eliminate gaps
8304         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8305                 batchneed |= BATCHNEED_NOGAPS;
8306
8307         // if needsupdate, we have to do a dynamic vertex batch for sure
8308         if (needsupdate & batchneed)
8309                 dynamicvertex = true;
8310
8311         // see if we need to build vertexmesh from arrays
8312         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8313                 dynamicvertex = true;
8314
8315         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8316         // also some drivers strongly dislike firstvertex
8317         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8318                 dynamicvertex = true;
8319
8320         rsurface.batchvertex3f = rsurface.modelvertex3f;
8321         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8322         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8323         rsurface.batchsvector3f = rsurface.modelsvector3f;
8324         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8325         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8326         rsurface.batchtvector3f = rsurface.modeltvector3f;
8327         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8328         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8329         rsurface.batchnormal3f = rsurface.modelnormal3f;
8330         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8331         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8332         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8333         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8334         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8335         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8336         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8337         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8338         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8339         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8340         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8341         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8342         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8343         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8344         rsurface.batchelement3i = rsurface.modelelement3i;
8345         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8346         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8347         rsurface.batchelement3s = rsurface.modelelement3s;
8348         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8349         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8350
8351         // if any dynamic vertex processing has to occur in software, we copy the
8352         // entire surface list together before processing to rebase the vertices
8353         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8354         //
8355         // if any gaps exist and we do not have a static vertex buffer, we have to
8356         // copy the surface list together to avoid wasting upload bandwidth on the
8357         // vertices in the gaps.
8358         //
8359         // if gaps exist and we have a static vertex buffer, we still have to
8360         // combine the index buffer ranges into one dynamic index buffer.
8361         //
8362         // in all cases we end up with data that can be drawn in one call.
8363
8364         if (!dynamicvertex)
8365         {
8366                 // static vertex data, just set pointers...
8367                 rsurface.batchgeneratedvertex = false;
8368                 // if there are gaps, we want to build a combined index buffer,
8369                 // otherwise use the original static buffer with an appropriate offset
8370                 if (gaps)
8371                 {
8372                         // build a new triangle elements array for this batch
8373                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8374                         rsurface.batchfirsttriangle = 0;
8375                         numtriangles = 0;
8376                         for (i = 0;i < texturenumsurfaces;i++)
8377                         {
8378                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8379                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8380                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8381                                 numtriangles += surfacenumtriangles;
8382                         }
8383                         rsurface.batchelement3i_indexbuffer = NULL;
8384                         rsurface.batchelement3i_bufferoffset = 0;
8385                         rsurface.batchelement3s = NULL;
8386                         rsurface.batchelement3s_indexbuffer = NULL;
8387                         rsurface.batchelement3s_bufferoffset = 0;
8388                         if (endvertex <= 65536)
8389                         {
8390                                 // make a 16bit (unsigned short) index array if possible
8391                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8392                                 for (i = 0;i < numtriangles*3;i++)
8393                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8394                         }
8395                 }
8396                 return;
8397         }
8398
8399         // something needs software processing, do it for real...
8400         // we only directly handle separate array data in this case and then
8401         // generate interleaved data if needed...
8402         rsurface.batchgeneratedvertex = true;
8403
8404         // now copy the vertex data into a combined array and make an index array
8405         // (this is what Quake3 does all the time)
8406         //if (gaps || rsurface.batchfirstvertex)
8407         {
8408                 rsurface.batchvertex3fbuffer = NULL;
8409                 rsurface.batchvertexmesh = NULL;
8410                 rsurface.batchvertexmeshbuffer = NULL;
8411                 rsurface.batchvertex3f = NULL;
8412                 rsurface.batchvertex3f_vertexbuffer = NULL;
8413                 rsurface.batchvertex3f_bufferoffset = 0;
8414                 rsurface.batchsvector3f = NULL;
8415                 rsurface.batchsvector3f_vertexbuffer = NULL;
8416                 rsurface.batchsvector3f_bufferoffset = 0;
8417                 rsurface.batchtvector3f = NULL;
8418                 rsurface.batchtvector3f_vertexbuffer = NULL;
8419                 rsurface.batchtvector3f_bufferoffset = 0;
8420                 rsurface.batchnormal3f = NULL;
8421                 rsurface.batchnormal3f_vertexbuffer = NULL;
8422                 rsurface.batchnormal3f_bufferoffset = 0;
8423                 rsurface.batchlightmapcolor4f = NULL;
8424                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8425                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8426                 rsurface.batchtexcoordtexture2f = NULL;
8427                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8428                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8429                 rsurface.batchtexcoordlightmap2f = NULL;
8430                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8431                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8432                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8433                 rsurface.batchelement3i_indexbuffer = NULL;
8434                 rsurface.batchelement3i_bufferoffset = 0;
8435                 rsurface.batchelement3s = NULL;
8436                 rsurface.batchelement3s_indexbuffer = NULL;
8437                 rsurface.batchelement3s_bufferoffset = 0;
8438                 // we'll only be setting up certain arrays as needed
8439                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8440                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8441                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8442                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8443                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8444                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8445                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8446                 {
8447                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8448                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8449                 }
8450                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8451                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8452                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8453                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8454                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8455                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8456                 numvertices = 0;
8457                 numtriangles = 0;
8458                 for (i = 0;i < texturenumsurfaces;i++)
8459                 {
8460                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8461                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8462                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8463                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8464                         // copy only the data requested
8465                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8466                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8467                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8468                         {
8469                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8470                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8471                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8472                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8473                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8474                                 {
8475                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8476                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8477                                 }
8478                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8479                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8480                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8481                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8482                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8483                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8484                         }
8485                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8486                         numvertices += surfacenumvertices;
8487                         numtriangles += surfacenumtriangles;
8488                 }
8489
8490                 // generate a 16bit index array as well if possible
8491                 // (in general, dynamic batches fit)
8492                 if (numvertices <= 65536)
8493                 {
8494                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8495                         for (i = 0;i < numtriangles*3;i++)
8496                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8497                 }
8498
8499                 // since we've copied everything, the batch now starts at 0
8500                 rsurface.batchfirstvertex = 0;
8501                 rsurface.batchnumvertices = batchnumvertices;
8502                 rsurface.batchfirsttriangle = 0;
8503                 rsurface.batchnumtriangles = batchnumtriangles;
8504         }
8505
8506         // q1bsp surfaces rendered in vertex color mode have to have colors
8507         // calculated based on lightstyles
8508         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8509         {
8510                 // generate color arrays for the surfaces in this list
8511                 int c[4];
8512                 int scale;
8513                 int size3;
8514                 const int *offsets;
8515                 const unsigned char *lm;
8516                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8517                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8518                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8519                 numvertices = 0;
8520                 for (i = 0;i < texturenumsurfaces;i++)
8521                 {
8522                         surface = texturesurfacelist[i];
8523                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8524                         surfacenumvertices = surface->num_vertices;
8525                         if (surface->lightmapinfo->samples)
8526                         {
8527                                 for (j = 0;j < surfacenumvertices;j++)
8528                                 {
8529                                         lm = surface->lightmapinfo->samples + offsets[j];
8530                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8531                                         VectorScale(lm, scale, c);
8532                                         if (surface->lightmapinfo->styles[1] != 255)
8533                                         {
8534                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8535                                                 lm += size3;
8536                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8537                                                 VectorMA(c, scale, lm, c);
8538                                                 if (surface->lightmapinfo->styles[2] != 255)
8539                                                 {
8540                                                         lm += size3;
8541                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8542                                                         VectorMA(c, scale, lm, c);
8543                                                         if (surface->lightmapinfo->styles[3] != 255)
8544                                                         {
8545                                                                 lm += size3;
8546                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8547                                                                 VectorMA(c, scale, lm, c);
8548                                                         }
8549                                                 }
8550                                         }
8551                                         c[0] >>= 7;
8552                                         c[1] >>= 7;
8553                                         c[2] >>= 7;
8554                                         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);
8555                                         numvertices++;
8556                                 }
8557                         }
8558                         else
8559                         {
8560                                 for (j = 0;j < surfacenumvertices;j++)
8561                                 {
8562                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8563                                         numvertices++;
8564                                 }
8565                         }
8566                 }
8567         }
8568
8569         // if vertices are deformed (sprite flares and things in maps, possibly
8570         // water waves, bulges and other deformations), modify the copied vertices
8571         // in place
8572         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8573         {
8574                 switch (deform->deform)
8575                 {
8576                 default:
8577                 case Q3DEFORM_PROJECTIONSHADOW:
8578                 case Q3DEFORM_TEXT0:
8579                 case Q3DEFORM_TEXT1:
8580                 case Q3DEFORM_TEXT2:
8581                 case Q3DEFORM_TEXT3:
8582                 case Q3DEFORM_TEXT4:
8583                 case Q3DEFORM_TEXT5:
8584                 case Q3DEFORM_TEXT6:
8585                 case Q3DEFORM_TEXT7:
8586                 case Q3DEFORM_NONE:
8587                         break;
8588                 case Q3DEFORM_AUTOSPRITE:
8589                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8590                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8591                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8592                         VectorNormalize(newforward);
8593                         VectorNormalize(newright);
8594                         VectorNormalize(newup);
8595 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8596 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8597 //                      rsurface.batchvertex3f_bufferoffset = 0;
8598 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8599 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8600 //                      rsurface.batchsvector3f_bufferoffset = 0;
8601 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8602 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8603 //                      rsurface.batchtvector3f_bufferoffset = 0;
8604 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8605 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8606 //                      rsurface.batchnormal3f_bufferoffset = 0;
8607                         // a single autosprite surface can contain multiple sprites...
8608                         for (j = 0;j < batchnumvertices - 3;j += 4)
8609                         {
8610                                 VectorClear(center);
8611                                 for (i = 0;i < 4;i++)
8612                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8613                                 VectorScale(center, 0.25f, center);
8614                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8615                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8616                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8617                                 for (i = 0;i < 4;i++)
8618                                 {
8619                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8620                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8621                                 }
8622                         }
8623                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8624                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8625                         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);
8626                         break;
8627                 case Q3DEFORM_AUTOSPRITE2:
8628                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8629                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8630                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8631                         VectorNormalize(newforward);
8632                         VectorNormalize(newright);
8633                         VectorNormalize(newup);
8634 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8635 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8636 //                      rsurface.batchvertex3f_bufferoffset = 0;
8637                         {
8638                                 const float *v1, *v2;
8639                                 vec3_t start, end;
8640                                 float f, l;
8641                                 struct
8642                                 {
8643                                         float length2;
8644                                         const float *v1;
8645                                         const float *v2;
8646                                 }
8647                                 shortest[2];
8648                                 memset(shortest, 0, sizeof(shortest));
8649                                 // a single autosprite surface can contain multiple sprites...
8650                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8651                                 {
8652                                         VectorClear(center);
8653                                         for (i = 0;i < 4;i++)
8654                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8655                                         VectorScale(center, 0.25f, center);
8656                                         // find the two shortest edges, then use them to define the
8657                                         // axis vectors for rotating around the central axis
8658                                         for (i = 0;i < 6;i++)
8659                                         {
8660                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8661                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8662                                                 l = VectorDistance2(v1, v2);
8663                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8664                                                 if (v1[2] != v2[2])
8665                                                         l += (1.0f / 1024.0f);
8666                                                 if (shortest[0].length2 > l || i == 0)
8667                                                 {
8668                                                         shortest[1] = shortest[0];
8669                                                         shortest[0].length2 = l;
8670                                                         shortest[0].v1 = v1;
8671                                                         shortest[0].v2 = v2;
8672                                                 }
8673                                                 else if (shortest[1].length2 > l || i == 1)
8674                                                 {
8675                                                         shortest[1].length2 = l;
8676                                                         shortest[1].v1 = v1;
8677                                                         shortest[1].v2 = v2;
8678                                                 }
8679                                         }
8680                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8681                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8682                                         // this calculates the right vector from the shortest edge
8683                                         // and the up vector from the edge midpoints
8684                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8685                                         VectorNormalize(right);
8686                                         VectorSubtract(end, start, up);
8687                                         VectorNormalize(up);
8688                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8689                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8690                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8691                                         VectorNegate(forward, forward);
8692                                         VectorReflect(forward, 0, up, forward);
8693                                         VectorNormalize(forward);
8694                                         CrossProduct(up, forward, newright);
8695                                         VectorNormalize(newright);
8696                                         // rotate the quad around the up axis vector, this is made
8697                                         // especially easy by the fact we know the quad is flat,
8698                                         // so we only have to subtract the center position and
8699                                         // measure distance along the right vector, and then
8700                                         // multiply that by the newright vector and add back the
8701                                         // center position
8702                                         // we also need to subtract the old position to undo the
8703                                         // displacement from the center, which we do with a
8704                                         // DotProduct, the subtraction/addition of center is also
8705                                         // optimized into DotProducts here
8706                                         l = DotProduct(right, center);
8707                                         for (i = 0;i < 4;i++)
8708                                         {
8709                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8710                                                 f = DotProduct(right, v1) - l;
8711                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8712                                         }
8713                                 }
8714                         }
8715                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8716                         {
8717 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8718 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8719 //                              rsurface.batchnormal3f_bufferoffset = 0;
8720                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8721                         }
8722                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8723                         {
8724 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8725 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8726 //                              rsurface.batchsvector3f_bufferoffset = 0;
8727 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8728 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8729 //                              rsurface.batchtvector3f_bufferoffset = 0;
8730                                 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);
8731                         }
8732                         break;
8733                 case Q3DEFORM_NORMAL:
8734                         // deform the normals to make reflections wavey
8735                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8736                         rsurface.batchnormal3f_vertexbuffer = NULL;
8737                         rsurface.batchnormal3f_bufferoffset = 0;
8738                         for (j = 0;j < batchnumvertices;j++)
8739                         {
8740                                 float vertex[3];
8741                                 float *normal = rsurface.batchnormal3f + 3*j;
8742                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8743                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8744                                 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]);
8745                                 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]);
8746                                 VectorNormalize(normal);
8747                         }
8748                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8749                         {
8750 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8751 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8752 //                              rsurface.batchsvector3f_bufferoffset = 0;
8753 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8754 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8755 //                              rsurface.batchtvector3f_bufferoffset = 0;
8756                                 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);
8757                         }
8758                         break;
8759                 case Q3DEFORM_WAVE:
8760                         // deform vertex array to make wavey water and flags and such
8761                         waveparms[0] = deform->waveparms[0];
8762                         waveparms[1] = deform->waveparms[1];
8763                         waveparms[2] = deform->waveparms[2];
8764                         waveparms[3] = deform->waveparms[3];
8765                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8766                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8767                         // this is how a divisor of vertex influence on deformation
8768                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8769                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8770 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8771 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8772 //                      rsurface.batchvertex3f_bufferoffset = 0;
8773 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8774 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8775 //                      rsurface.batchnormal3f_bufferoffset = 0;
8776                         for (j = 0;j < batchnumvertices;j++)
8777                         {
8778                                 // if the wavefunc depends on time, evaluate it per-vertex
8779                                 if (waveparms[3])
8780                                 {
8781                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8782                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8783                                 }
8784                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8785                         }
8786                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8787                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8788                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8789                         {
8790 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8791 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8792 //                              rsurface.batchsvector3f_bufferoffset = 0;
8793 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8794 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8795 //                              rsurface.batchtvector3f_bufferoffset = 0;
8796                                 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);
8797                         }
8798                         break;
8799                 case Q3DEFORM_BULGE:
8800                         // deform vertex array to make the surface have moving bulges
8801 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8802 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8803 //                      rsurface.batchvertex3f_bufferoffset = 0;
8804 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8805 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8806 //                      rsurface.batchnormal3f_bufferoffset = 0;
8807                         for (j = 0;j < batchnumvertices;j++)
8808                         {
8809                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8810                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8811                         }
8812                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8813                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8814                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8815                         {
8816 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8817 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8818 //                              rsurface.batchsvector3f_bufferoffset = 0;
8819 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8820 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8821 //                              rsurface.batchtvector3f_bufferoffset = 0;
8822                                 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);
8823                         }
8824                         break;
8825                 case Q3DEFORM_MOVE:
8826                         // deform vertex array
8827                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8828                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8829                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8830                         VectorScale(deform->parms, scale, waveparms);
8831 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8832 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8833 //                      rsurface.batchvertex3f_bufferoffset = 0;
8834                         for (j = 0;j < batchnumvertices;j++)
8835                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8836                         break;
8837                 }
8838         }
8839
8840         // generate texcoords based on the chosen texcoord source
8841         switch(rsurface.texture->tcgen.tcgen)
8842         {
8843         default:
8844         case Q3TCGEN_TEXTURE:
8845                 break;
8846         case Q3TCGEN_LIGHTMAP:
8847 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8848 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8849 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8850                 if (rsurface.batchtexcoordlightmap2f)
8851                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8852                 break;
8853         case Q3TCGEN_VECTOR:
8854 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8855 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8856 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8857                 for (j = 0;j < batchnumvertices;j++)
8858                 {
8859                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8860                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8861                 }
8862                 break;
8863         case Q3TCGEN_ENVIRONMENT:
8864                 // make environment reflections using a spheremap
8865                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8866                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8867                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8868                 for (j = 0;j < batchnumvertices;j++)
8869                 {
8870                         // identical to Q3A's method, but executed in worldspace so
8871                         // carried models can be shiny too
8872
8873                         float viewer[3], d, reflected[3], worldreflected[3];
8874
8875                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8876                         // VectorNormalize(viewer);
8877
8878                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8879
8880                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8881                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8882                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8883                         // note: this is proportinal to viewer, so we can normalize later
8884
8885                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8886                         VectorNormalize(worldreflected);
8887
8888                         // note: this sphere map only uses world x and z!
8889                         // so positive and negative y will LOOK THE SAME.
8890                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8891                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8892                 }
8893                 break;
8894         }
8895         // the only tcmod that needs software vertex processing is turbulent, so
8896         // check for it here and apply the changes if needed
8897         // and we only support that as the first one
8898         // (handling a mixture of turbulent and other tcmods would be problematic
8899         //  without punting it entirely to a software path)
8900         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8901         {
8902                 amplitude = rsurface.texture->tcmods[0].parms[1];
8903                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8904 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8905 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8906 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8907                 for (j = 0;j < batchnumvertices;j++)
8908                 {
8909                         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);
8910                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8911                 }
8912         }
8913
8914         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8915         {
8916                 // convert the modified arrays to vertex structs
8917 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8918 //              rsurface.batchvertexmeshbuffer = NULL;
8919                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8920                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8921                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8922                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8923                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8924                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8925                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8926                 {
8927                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8928                         {
8929                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8930                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8931                         }
8932                 }
8933                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8934                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8935                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8936                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8937                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8938                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8939                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8940                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8941                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8942         }
8943 }
8944
8945 void RSurf_DrawBatch(void)
8946 {
8947         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8948         // through the pipeline, killing it earlier in the pipeline would have
8949         // per-surface overhead rather than per-batch overhead, so it's best to
8950         // reject it here, before it hits glDraw.
8951         if (rsurface.batchnumtriangles == 0)
8952                 return;
8953 #if 0
8954         // batch debugging code
8955         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8956         {
8957                 int i;
8958                 int j;
8959                 int c;
8960                 const int *e;
8961                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8962                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8963                 {
8964                         c = e[i];
8965                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8966                         {
8967                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8968                                 {
8969                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8970                                                 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);
8971                                         break;
8972                                 }
8973                         }
8974                 }
8975         }
8976 #endif
8977         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);
8978 }
8979
8980 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8981 {
8982         // pick the closest matching water plane
8983         int planeindex, vertexindex, bestplaneindex = -1;
8984         float d, bestd;
8985         vec3_t vert;
8986         const float *v;
8987         r_waterstate_waterplane_t *p;
8988         qboolean prepared = false;
8989         bestd = 0;
8990         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8991         {
8992                 if(p->camera_entity != rsurface.texture->camera_entity)
8993                         continue;
8994                 d = 0;
8995                 if(!prepared)
8996                 {
8997                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8998                         prepared = true;
8999                         if(rsurface.batchnumvertices == 0)
9000                                 break;
9001                 }
9002                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9003                 {
9004                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9005                         d += fabs(PlaneDiff(vert, &p->plane));
9006                 }
9007                 if (bestd > d || bestplaneindex < 0)
9008                 {
9009                         bestd = d;
9010                         bestplaneindex = planeindex;
9011                 }
9012         }
9013         return bestplaneindex;
9014         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9015         // this situation though, as it might be better to render single larger
9016         // batches with useless stuff (backface culled for example) than to
9017         // render multiple smaller batches
9018 }
9019
9020 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9021 {
9022         int i;
9023         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9024         rsurface.passcolor4f_vertexbuffer = 0;
9025         rsurface.passcolor4f_bufferoffset = 0;
9026         for (i = 0;i < rsurface.batchnumvertices;i++)
9027                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9028 }
9029
9030 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9031 {
9032         int i;
9033         float f;
9034         const float *v;
9035         const float *c;
9036         float *c2;
9037         if (rsurface.passcolor4f)
9038         {
9039                 // generate color arrays
9040                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9041                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9042                 rsurface.passcolor4f_vertexbuffer = 0;
9043                 rsurface.passcolor4f_bufferoffset = 0;
9044                 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)
9045                 {
9046                         f = RSurf_FogVertex(v);
9047                         c2[0] = c[0] * f;
9048                         c2[1] = c[1] * f;
9049                         c2[2] = c[2] * f;
9050                         c2[3] = c[3];
9051                 }
9052         }
9053         else
9054         {
9055                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9056                 rsurface.passcolor4f_vertexbuffer = 0;
9057                 rsurface.passcolor4f_bufferoffset = 0;
9058                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9059                 {
9060                         f = RSurf_FogVertex(v);
9061                         c2[0] = f;
9062                         c2[1] = f;
9063                         c2[2] = f;
9064                         c2[3] = 1;
9065                 }
9066         }
9067 }
9068
9069 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9070 {
9071         int i;
9072         float f;
9073         const float *v;
9074         const float *c;
9075         float *c2;
9076         if (!rsurface.passcolor4f)
9077                 return;
9078         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9079         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9080         rsurface.passcolor4f_vertexbuffer = 0;
9081         rsurface.passcolor4f_bufferoffset = 0;
9082         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)
9083         {
9084                 f = RSurf_FogVertex(v);
9085                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9086                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9087                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9088                 c2[3] = c[3];
9089         }
9090 }
9091
9092 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9093 {
9094         int i;
9095         const float *c;
9096         float *c2;
9097         if (!rsurface.passcolor4f)
9098                 return;
9099         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9100         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9101         rsurface.passcolor4f_vertexbuffer = 0;
9102         rsurface.passcolor4f_bufferoffset = 0;
9103         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9104         {
9105                 c2[0] = c[0] * r;
9106                 c2[1] = c[1] * g;
9107                 c2[2] = c[2] * b;
9108                 c2[3] = c[3] * a;
9109         }
9110 }
9111
9112 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9113 {
9114         int i;
9115         const float *c;
9116         float *c2;
9117         if (!rsurface.passcolor4f)
9118                 return;
9119         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9120         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9121         rsurface.passcolor4f_vertexbuffer = 0;
9122         rsurface.passcolor4f_bufferoffset = 0;
9123         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9124         {
9125                 c2[0] = c[0] + r_refdef.scene.ambient;
9126                 c2[1] = c[1] + r_refdef.scene.ambient;
9127                 c2[2] = c[2] + r_refdef.scene.ambient;
9128                 c2[3] = c[3];
9129         }
9130 }
9131
9132 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9133 {
9134         // TODO: optimize
9135         rsurface.passcolor4f = NULL;
9136         rsurface.passcolor4f_vertexbuffer = 0;
9137         rsurface.passcolor4f_bufferoffset = 0;
9138         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9139         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9140         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9141         GL_Color(r, g, b, a);
9142         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9143         RSurf_DrawBatch();
9144 }
9145
9146 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9147 {
9148         // TODO: optimize applyfog && applycolor case
9149         // just apply fog if necessary, and tint the fog color array if necessary
9150         rsurface.passcolor4f = NULL;
9151         rsurface.passcolor4f_vertexbuffer = 0;
9152         rsurface.passcolor4f_bufferoffset = 0;
9153         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9154         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9155         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9156         GL_Color(r, g, b, a);
9157         RSurf_DrawBatch();
9158 }
9159
9160 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9161 {
9162         // TODO: optimize
9163         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9164         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9165         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9166         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9167         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9168         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9169         GL_Color(r, g, b, a);
9170         RSurf_DrawBatch();
9171 }
9172
9173 static void RSurf_DrawBatch_GL11_ClampColor(void)
9174 {
9175         int i;
9176         const float *c1;
9177         float *c2;
9178         if (!rsurface.passcolor4f)
9179                 return;
9180         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9181         {
9182                 c2[0] = bound(0.0f, c1[0], 1.0f);
9183                 c2[1] = bound(0.0f, c1[1], 1.0f);
9184                 c2[2] = bound(0.0f, c1[2], 1.0f);
9185                 c2[3] = bound(0.0f, c1[3], 1.0f);
9186         }
9187 }
9188
9189 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9190 {
9191         int i;
9192         float f;
9193         const float *v;
9194         const float *n;
9195         float *c;
9196         //vec3_t eyedir;
9197
9198         // fake shading
9199         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9200         rsurface.passcolor4f_vertexbuffer = 0;
9201         rsurface.passcolor4f_bufferoffset = 0;
9202         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)
9203         {
9204                 f = -DotProduct(r_refdef.view.forward, n);
9205                 f = max(0, f);
9206                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9207                 f *= r_refdef.lightmapintensity;
9208                 Vector4Set(c, f, f, f, 1);
9209         }
9210 }
9211
9212 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9213 {
9214         RSurf_DrawBatch_GL11_ApplyFakeLight();
9215         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9216         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9217         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9218         GL_Color(r, g, b, a);
9219         RSurf_DrawBatch();
9220 }
9221
9222 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9223 {
9224         int i;
9225         float f;
9226         float alpha;
9227         const float *v;
9228         const float *n;
9229         float *c;
9230         vec3_t ambientcolor;
9231         vec3_t diffusecolor;
9232         vec3_t lightdir;
9233         // TODO: optimize
9234         // model lighting
9235         VectorCopy(rsurface.modellight_lightdir, lightdir);
9236         f = 0.5f * r_refdef.lightmapintensity;
9237         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9238         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9239         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9240         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9241         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9242         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9243         alpha = *a;
9244         if (VectorLength2(diffusecolor) > 0)
9245         {
9246                 // q3-style directional shading
9247                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9248                 rsurface.passcolor4f_vertexbuffer = 0;
9249                 rsurface.passcolor4f_bufferoffset = 0;
9250                 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)
9251                 {
9252                         if ((f = DotProduct(n, lightdir)) > 0)
9253                                 VectorMA(ambientcolor, f, diffusecolor, c);
9254                         else
9255                                 VectorCopy(ambientcolor, c);
9256                         c[3] = alpha;
9257                 }
9258                 *r = 1;
9259                 *g = 1;
9260                 *b = 1;
9261                 *a = 1;
9262                 *applycolor = false;
9263         }
9264         else
9265         {
9266                 *r = ambientcolor[0];
9267                 *g = ambientcolor[1];
9268                 *b = ambientcolor[2];
9269                 rsurface.passcolor4f = NULL;
9270                 rsurface.passcolor4f_vertexbuffer = 0;
9271                 rsurface.passcolor4f_bufferoffset = 0;
9272         }
9273 }
9274
9275 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9276 {
9277         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9278         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9279         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9280         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9281         GL_Color(r, g, b, a);
9282         RSurf_DrawBatch();
9283 }
9284
9285 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9286 {
9287         int i;
9288         float f;
9289         const float *v;
9290         float *c;
9291
9292         // fake shading
9293         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9294         rsurface.passcolor4f_vertexbuffer = 0;
9295         rsurface.passcolor4f_bufferoffset = 0;
9296
9297         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9298         {
9299                 f = 1 - RSurf_FogVertex(v);
9300                 c[0] = r;
9301                 c[1] = g;
9302                 c[2] = b;
9303                 c[3] = f * a;
9304         }
9305 }
9306
9307 void RSurf_SetupDepthAndCulling(void)
9308 {
9309         // submodels are biased to avoid z-fighting with world surfaces that they
9310         // may be exactly overlapping (avoids z-fighting artifacts on certain
9311         // doors and things in Quake maps)
9312         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9313         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9314         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9315         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9316 }
9317
9318 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9319 {
9320         // transparent sky would be ridiculous
9321         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9322                 return;
9323         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9324         skyrenderlater = true;
9325         RSurf_SetupDepthAndCulling();
9326         GL_DepthMask(true);
9327         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9328         // skymasking on them, and Quake3 never did sky masking (unlike
9329         // software Quake and software Quake2), so disable the sky masking
9330         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9331         // and skymasking also looks very bad when noclipping outside the
9332         // level, so don't use it then either.
9333         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9334         {
9335                 R_Mesh_ResetTextureState();
9336                 if (skyrendermasked)
9337                 {
9338                         R_SetupShader_DepthOrShadow();
9339                         // depth-only (masking)
9340                         GL_ColorMask(0,0,0,0);
9341                         // just to make sure that braindead drivers don't draw
9342                         // anything despite that colormask...
9343                         GL_BlendFunc(GL_ZERO, GL_ONE);
9344                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9345                         if (rsurface.batchvertex3fbuffer)
9346                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9347                         else
9348                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9349                 }
9350                 else
9351                 {
9352                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9353                         // fog sky
9354                         GL_BlendFunc(GL_ONE, GL_ZERO);
9355                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9356                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9357                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9358                 }
9359                 RSurf_DrawBatch();
9360                 if (skyrendermasked)
9361                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9362         }
9363         R_Mesh_ResetTextureState();
9364         GL_Color(1, 1, 1, 1);
9365 }
9366
9367 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9368 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9369 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9370 {
9371         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9372                 return;
9373         if (prepass)
9374         {
9375                 // render screenspace normalmap to texture
9376                 GL_DepthMask(true);
9377                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9378                 RSurf_DrawBatch();
9379                 return;
9380         }
9381
9382         // bind lightmap texture
9383
9384         // water/refraction/reflection/camera surfaces have to be handled specially
9385         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9386         {
9387                 int start, end, startplaneindex;
9388                 for (start = 0;start < texturenumsurfaces;start = end)
9389                 {
9390                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9391                         if(startplaneindex < 0)
9392                         {
9393                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9394                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9395                                 end = start + 1;
9396                                 continue;
9397                         }
9398                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9399                                 ;
9400                         // now that we have a batch using the same planeindex, render it
9401                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9402                         {
9403                                 // render water or distortion background
9404                                 GL_DepthMask(true);
9405                                 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));
9406                                 RSurf_DrawBatch();
9407                                 // blend surface on top
9408                                 GL_DepthMask(false);
9409                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9410                                 RSurf_DrawBatch();
9411                         }
9412                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9413                         {
9414                                 // render surface with reflection texture as input
9415                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9416                                 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));
9417                                 RSurf_DrawBatch();
9418                         }
9419                 }
9420                 return;
9421         }
9422
9423         // render surface batch normally
9424         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9425         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9426         RSurf_DrawBatch();
9427 }
9428
9429 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9430 {
9431         // OpenGL 1.3 path - anything not completely ancient
9432         qboolean applycolor;
9433         qboolean applyfog;
9434         int layerindex;
9435         const texturelayer_t *layer;
9436         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);
9437         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9438
9439         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9440         {
9441                 vec4_t layercolor;
9442                 int layertexrgbscale;
9443                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9444                 {
9445                         if (layerindex == 0)
9446                                 GL_AlphaTest(true);
9447                         else
9448                         {
9449                                 GL_AlphaTest(false);
9450                                 GL_DepthFunc(GL_EQUAL);
9451                         }
9452                 }
9453                 GL_DepthMask(layer->depthmask && writedepth);
9454                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9455                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9456                 {
9457                         layertexrgbscale = 4;
9458                         VectorScale(layer->color, 0.25f, layercolor);
9459                 }
9460                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9461                 {
9462                         layertexrgbscale = 2;
9463                         VectorScale(layer->color, 0.5f, layercolor);
9464                 }
9465                 else
9466                 {
9467                         layertexrgbscale = 1;
9468                         VectorScale(layer->color, 1.0f, layercolor);
9469                 }
9470                 layercolor[3] = layer->color[3];
9471                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9472                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9473                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9474                 switch (layer->type)
9475                 {
9476                 case TEXTURELAYERTYPE_LITTEXTURE:
9477                         // single-pass lightmapped texture with 2x rgbscale
9478                         R_Mesh_TexBind(0, r_texture_white);
9479                         R_Mesh_TexMatrix(0, NULL);
9480                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9481                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9482                         R_Mesh_TexBind(1, layer->texture);
9483                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9484                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9485                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9486                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9487                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9488                         else if (FAKELIGHT_ENABLED)
9489                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9490                         else if (rsurface.uselightmaptexture)
9491                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9492                         else
9493                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9494                         break;
9495                 case TEXTURELAYERTYPE_TEXTURE:
9496                         // singletexture unlit texture with transparency support
9497                         R_Mesh_TexBind(0, layer->texture);
9498                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9499                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9500                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9501                         R_Mesh_TexBind(1, 0);
9502                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9503                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9504                         break;
9505                 case TEXTURELAYERTYPE_FOG:
9506                         // singletexture fogging
9507                         if (layer->texture)
9508                         {
9509                                 R_Mesh_TexBind(0, layer->texture);
9510                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9511                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9512                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9513                         }
9514                         else
9515                         {
9516                                 R_Mesh_TexBind(0, 0);
9517                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9518                         }
9519                         R_Mesh_TexBind(1, 0);
9520                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9521                         // generate a color array for the fog pass
9522                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9523                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9524                         RSurf_DrawBatch();
9525                         break;
9526                 default:
9527                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9528                 }
9529         }
9530         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9531         {
9532                 GL_DepthFunc(GL_LEQUAL);
9533                 GL_AlphaTest(false);
9534         }
9535 }
9536
9537 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9538 {
9539         // OpenGL 1.1 - crusty old voodoo path
9540         qboolean applyfog;
9541         int layerindex;
9542         const texturelayer_t *layer;
9543         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);
9544         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9545
9546         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9547         {
9548                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9549                 {
9550                         if (layerindex == 0)
9551                                 GL_AlphaTest(true);
9552                         else
9553                         {
9554                                 GL_AlphaTest(false);
9555                                 GL_DepthFunc(GL_EQUAL);
9556                         }
9557                 }
9558                 GL_DepthMask(layer->depthmask && writedepth);
9559                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9560                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9561                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9562                 switch (layer->type)
9563                 {
9564                 case TEXTURELAYERTYPE_LITTEXTURE:
9565                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9566                         {
9567                                 // two-pass lit texture with 2x rgbscale
9568                                 // first the lightmap pass
9569                                 R_Mesh_TexBind(0, r_texture_white);
9570                                 R_Mesh_TexMatrix(0, NULL);
9571                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9572                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9573                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9574                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9575                                 else if (FAKELIGHT_ENABLED)
9576                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9577                                 else if (rsurface.uselightmaptexture)
9578                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9579                                 else
9580                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9581                                 // then apply the texture to it
9582                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9583                                 R_Mesh_TexBind(0, layer->texture);
9584                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9585                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9586                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9587                                 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);
9588                         }
9589                         else
9590                         {
9591                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9592                                 R_Mesh_TexBind(0, layer->texture);
9593                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9594                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9595                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9596                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9597                                         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);
9598                                 else
9599                                         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);
9600                         }
9601                         break;
9602                 case TEXTURELAYERTYPE_TEXTURE:
9603                         // singletexture unlit texture with transparency support
9604                         R_Mesh_TexBind(0, layer->texture);
9605                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9606                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9607                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9608                         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);
9609                         break;
9610                 case TEXTURELAYERTYPE_FOG:
9611                         // singletexture fogging
9612                         if (layer->texture)
9613                         {
9614                                 R_Mesh_TexBind(0, layer->texture);
9615                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9616                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9617                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9618                         }
9619                         else
9620                         {
9621                                 R_Mesh_TexBind(0, 0);
9622                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9623                         }
9624                         // generate a color array for the fog pass
9625                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9626                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9627                         RSurf_DrawBatch();
9628                         break;
9629                 default:
9630                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9631                 }
9632         }
9633         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9634         {
9635                 GL_DepthFunc(GL_LEQUAL);
9636                 GL_AlphaTest(false);
9637         }
9638 }
9639
9640 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9641 {
9642         int vi;
9643         int j;
9644         r_vertexgeneric_t *batchvertex;
9645         float c[4];
9646
9647 //      R_Mesh_ResetTextureState();
9648         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9649
9650         if(rsurface.texture && rsurface.texture->currentskinframe)
9651         {
9652                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9653                 c[3] *= rsurface.texture->currentalpha;
9654         }
9655         else
9656         {
9657                 c[0] = 1;
9658                 c[1] = 0;
9659                 c[2] = 1;
9660                 c[3] = 1;
9661         }
9662
9663         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9664         {
9665                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9666                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9667                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9668         }
9669
9670         // brighten it up (as texture value 127 means "unlit")
9671         c[0] *= 2 * r_refdef.view.colorscale;
9672         c[1] *= 2 * r_refdef.view.colorscale;
9673         c[2] *= 2 * r_refdef.view.colorscale;
9674
9675         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9676                 c[3] *= r_wateralpha.value;
9677
9678         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9679         {
9680                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9681                 GL_DepthMask(false);
9682         }
9683         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9684         {
9685                 GL_BlendFunc(GL_ONE, GL_ONE);
9686                 GL_DepthMask(false);
9687         }
9688         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9689         {
9690                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9691                 GL_DepthMask(false);
9692         }
9693         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9694         {
9695                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9696                 GL_DepthMask(false);
9697         }
9698         else
9699         {
9700                 GL_BlendFunc(GL_ONE, GL_ZERO);
9701                 GL_DepthMask(writedepth);
9702         }
9703
9704         if (r_showsurfaces.integer == 3)
9705         {
9706                 rsurface.passcolor4f = NULL;
9707
9708                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9709                 {
9710                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9711
9712                         rsurface.passcolor4f = NULL;
9713                         rsurface.passcolor4f_vertexbuffer = 0;
9714                         rsurface.passcolor4f_bufferoffset = 0;
9715                 }
9716                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9717                 {
9718                         qboolean applycolor = true;
9719                         float one = 1.0;
9720
9721                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9722
9723                         r_refdef.lightmapintensity = 1;
9724                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9725                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9726                 }
9727                 else if (FAKELIGHT_ENABLED)
9728                 {
9729                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9730
9731                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9732                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9733                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9734                 }
9735                 else
9736                 {
9737                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9738
9739                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9740                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9741                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9742                 }
9743
9744                 if(!rsurface.passcolor4f)
9745                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9746
9747                 RSurf_DrawBatch_GL11_ApplyAmbient();
9748                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9749                 if(r_refdef.fogenabled)
9750                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9751                 RSurf_DrawBatch_GL11_ClampColor();
9752
9753                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9754                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9755                 RSurf_DrawBatch();
9756         }
9757         else if (!r_refdef.view.showdebug)
9758         {
9759                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9760                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9761                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9762                 {
9763                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9764                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9765                 }
9766                 R_Mesh_PrepareVertices_Generic_Unlock();
9767                 RSurf_DrawBatch();
9768         }
9769         else if (r_showsurfaces.integer == 4)
9770         {
9771                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9772                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9773                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9774                 {
9775                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9776                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9777                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9778                 }
9779                 R_Mesh_PrepareVertices_Generic_Unlock();
9780                 RSurf_DrawBatch();
9781         }
9782         else if (r_showsurfaces.integer == 2)
9783         {
9784                 const int *e;
9785                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9786                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9787                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9788                 {
9789                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9790                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9791                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9792                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9793                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9794                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9795                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9796                 }
9797                 R_Mesh_PrepareVertices_Generic_Unlock();
9798                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9799         }
9800         else
9801         {
9802                 int texturesurfaceindex;
9803                 int k;
9804                 const msurface_t *surface;
9805                 float surfacecolor4f[4];
9806                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9807                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9808                 vi = 0;
9809                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9810                 {
9811                         surface = texturesurfacelist[texturesurfaceindex];
9812                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9813                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9814                         for (j = 0;j < surface->num_vertices;j++)
9815                         {
9816                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9817                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9818                                 vi++;
9819                         }
9820                 }
9821                 R_Mesh_PrepareVertices_Generic_Unlock();
9822                 RSurf_DrawBatch();
9823         }
9824 }
9825
9826 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9827 {
9828         CHECKGLERROR
9829         RSurf_SetupDepthAndCulling();
9830         if (r_showsurfaces.integer)
9831         {
9832                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9833                 return;
9834         }
9835         switch (vid.renderpath)
9836         {
9837         case RENDERPATH_GL20:
9838         case RENDERPATH_D3D9:
9839         case RENDERPATH_D3D10:
9840         case RENDERPATH_D3D11:
9841         case RENDERPATH_SOFT:
9842         case RENDERPATH_GLES2:
9843                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9844                 break;
9845         case RENDERPATH_GL13:
9846                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9847                 break;
9848         case RENDERPATH_GL11:
9849                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9850                 break;
9851         }
9852         CHECKGLERROR
9853 }
9854
9855 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9856 {
9857         CHECKGLERROR
9858         RSurf_SetupDepthAndCulling();
9859         if (r_showsurfaces.integer)
9860         {
9861                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9862                 return;
9863         }
9864         switch (vid.renderpath)
9865         {
9866         case RENDERPATH_GL20:
9867         case RENDERPATH_D3D9:
9868         case RENDERPATH_D3D10:
9869         case RENDERPATH_D3D11:
9870         case RENDERPATH_SOFT:
9871         case RENDERPATH_GLES2:
9872                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9873                 break;
9874         case RENDERPATH_GL13:
9875                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9876                 break;
9877         case RENDERPATH_GL11:
9878                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9879                 break;
9880         }
9881         CHECKGLERROR
9882 }
9883
9884 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9885 {
9886         int i, j;
9887         int texturenumsurfaces, endsurface;
9888         texture_t *texture;
9889         const msurface_t *surface;
9890 #define MAXBATCH_TRANSPARENTSURFACES 256
9891         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9892
9893         // if the model is static it doesn't matter what value we give for
9894         // wantnormals and wanttangents, so this logic uses only rules applicable
9895         // to a model, knowing that they are meaningless otherwise
9896         if (ent == r_refdef.scene.worldentity)
9897                 RSurf_ActiveWorldEntity();
9898         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9899                 RSurf_ActiveModelEntity(ent, false, false, false);
9900         else
9901         {
9902                 switch (vid.renderpath)
9903                 {
9904                 case RENDERPATH_GL20:
9905                 case RENDERPATH_D3D9:
9906                 case RENDERPATH_D3D10:
9907                 case RENDERPATH_D3D11:
9908                 case RENDERPATH_SOFT:
9909                 case RENDERPATH_GLES2:
9910                         RSurf_ActiveModelEntity(ent, true, true, false);
9911                         break;
9912                 case RENDERPATH_GL13:
9913                 case RENDERPATH_GL11:
9914                         RSurf_ActiveModelEntity(ent, true, false, false);
9915                         break;
9916                 }
9917         }
9918
9919         if (r_transparentdepthmasking.integer)
9920         {
9921                 qboolean setup = false;
9922                 for (i = 0;i < numsurfaces;i = j)
9923                 {
9924                         j = i + 1;
9925                         surface = rsurface.modelsurfaces + surfacelist[i];
9926                         texture = surface->texture;
9927                         rsurface.texture = R_GetCurrentTexture(texture);
9928                         rsurface.lightmaptexture = NULL;
9929                         rsurface.deluxemaptexture = NULL;
9930                         rsurface.uselightmaptexture = false;
9931                         // scan ahead until we find a different texture
9932                         endsurface = min(i + 1024, numsurfaces);
9933                         texturenumsurfaces = 0;
9934                         texturesurfacelist[texturenumsurfaces++] = surface;
9935                         for (;j < endsurface;j++)
9936                         {
9937                                 surface = rsurface.modelsurfaces + surfacelist[j];
9938                                 if (texture != surface->texture)
9939                                         break;
9940                                 texturesurfacelist[texturenumsurfaces++] = surface;
9941                         }
9942                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9943                                 continue;
9944                         // render the range of surfaces as depth
9945                         if (!setup)
9946                         {
9947                                 setup = true;
9948                                 GL_ColorMask(0,0,0,0);
9949                                 GL_Color(1,1,1,1);
9950                                 GL_DepthTest(true);
9951                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9952                                 GL_DepthMask(true);
9953 //                              R_Mesh_ResetTextureState();
9954                                 R_SetupShader_DepthOrShadow();
9955                         }
9956                         RSurf_SetupDepthAndCulling();
9957                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9958                         if (rsurface.batchvertex3fbuffer)
9959                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9960                         else
9961                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9962                         RSurf_DrawBatch();
9963                 }
9964                 if (setup)
9965                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9966         }
9967
9968         for (i = 0;i < numsurfaces;i = j)
9969         {
9970                 j = i + 1;
9971                 surface = rsurface.modelsurfaces + surfacelist[i];
9972                 texture = surface->texture;
9973                 rsurface.texture = R_GetCurrentTexture(texture);
9974                 // scan ahead until we find a different texture
9975                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9976                 texturenumsurfaces = 0;
9977                 texturesurfacelist[texturenumsurfaces++] = surface;
9978                 if(FAKELIGHT_ENABLED)
9979                 {
9980                         rsurface.lightmaptexture = NULL;
9981                         rsurface.deluxemaptexture = NULL;
9982                         rsurface.uselightmaptexture = false;
9983                         for (;j < endsurface;j++)
9984                         {
9985                                 surface = rsurface.modelsurfaces + surfacelist[j];
9986                                 if (texture != surface->texture)
9987                                         break;
9988                                 texturesurfacelist[texturenumsurfaces++] = surface;
9989                         }
9990                 }
9991                 else
9992                 {
9993                         rsurface.lightmaptexture = surface->lightmaptexture;
9994                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9995                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9996                         for (;j < endsurface;j++)
9997                         {
9998                                 surface = rsurface.modelsurfaces + surfacelist[j];
9999                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10000                                         break;
10001                                 texturesurfacelist[texturenumsurfaces++] = surface;
10002                         }
10003                 }
10004                 // render the range of surfaces
10005                 if (ent == r_refdef.scene.worldentity)
10006                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10007                 else
10008                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10009         }
10010         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10011 }
10012
10013 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10014 {
10015         // transparent surfaces get pushed off into the transparent queue
10016         int surfacelistindex;
10017         const msurface_t *surface;
10018         vec3_t tempcenter, center;
10019         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10020         {
10021                 surface = texturesurfacelist[surfacelistindex];
10022                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10023                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10024                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10025                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10026                 if (queueentity->transparent_offset) // transparent offset
10027                 {
10028                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10029                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10030                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10031                 }
10032                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10033         }
10034 }
10035
10036 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10037 {
10038         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10039                 return;
10040         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10041                 return;
10042         RSurf_SetupDepthAndCulling();
10043         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10044         if (rsurface.batchvertex3fbuffer)
10045                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10046         else
10047                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10048         RSurf_DrawBatch();
10049 }
10050
10051 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10052 {
10053         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10054         CHECKGLERROR
10055         if (depthonly)
10056                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10057         else if (prepass)
10058         {
10059                 if (!rsurface.texture->currentnumlayers)
10060                         return;
10061                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10062                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10063                 else
10064                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10065         }
10066         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10067                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10068         else if (!rsurface.texture->currentnumlayers)
10069                 return;
10070         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10071         {
10072                 // in the deferred case, transparent surfaces were queued during prepass
10073                 if (!r_shadow_usingdeferredprepass)
10074                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10075         }
10076         else
10077         {
10078                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10079                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10080         }
10081         CHECKGLERROR
10082 }
10083
10084 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10085 {
10086         int i, j;
10087         texture_t *texture;
10088         R_FrameData_SetMark();
10089         // break the surface list down into batches by texture and use of lightmapping
10090         for (i = 0;i < numsurfaces;i = j)
10091         {
10092                 j = i + 1;
10093                 // texture is the base texture pointer, rsurface.texture is the
10094                 // current frame/skin the texture is directing us to use (for example
10095                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10096                 // use skin 1 instead)
10097                 texture = surfacelist[i]->texture;
10098                 rsurface.texture = R_GetCurrentTexture(texture);
10099                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10100                 {
10101                         // if this texture is not the kind we want, skip ahead to the next one
10102                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10103                                 ;
10104                         continue;
10105                 }
10106                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10107                 {
10108                         rsurface.lightmaptexture = NULL;
10109                         rsurface.deluxemaptexture = NULL;
10110                         rsurface.uselightmaptexture = false;
10111                         // simply scan ahead until we find a different texture or lightmap state
10112                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10113                                 ;
10114                 }
10115                 else
10116                 {
10117                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10118                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10119                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10120                         // simply scan ahead until we find a different texture or lightmap state
10121                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10122                                 ;
10123                 }
10124                 // render the range of surfaces
10125                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10126         }
10127         R_FrameData_ReturnToMark();
10128 }
10129
10130 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10131 {
10132         CHECKGLERROR
10133         if (depthonly)
10134                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10135         else if (prepass)
10136         {
10137                 if (!rsurface.texture->currentnumlayers)
10138                         return;
10139                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10140                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10141                 else
10142                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10143         }
10144         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10145                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10146         else if (!rsurface.texture->currentnumlayers)
10147                 return;
10148         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10149         {
10150                 // in the deferred case, transparent surfaces were queued during prepass
10151                 if (!r_shadow_usingdeferredprepass)
10152                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10153         }
10154         else
10155         {
10156                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10157                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10158         }
10159         CHECKGLERROR
10160 }
10161
10162 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10163 {
10164         int i, j;
10165         texture_t *texture;
10166         R_FrameData_SetMark();
10167         // break the surface list down into batches by texture and use of lightmapping
10168         for (i = 0;i < numsurfaces;i = j)
10169         {
10170                 j = i + 1;
10171                 // texture is the base texture pointer, rsurface.texture is the
10172                 // current frame/skin the texture is directing us to use (for example
10173                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10174                 // use skin 1 instead)
10175                 texture = surfacelist[i]->texture;
10176                 rsurface.texture = R_GetCurrentTexture(texture);
10177                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10178                 {
10179                         // if this texture is not the kind we want, skip ahead to the next one
10180                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10181                                 ;
10182                         continue;
10183                 }
10184                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10185                 {
10186                         rsurface.lightmaptexture = NULL;
10187                         rsurface.deluxemaptexture = NULL;
10188                         rsurface.uselightmaptexture = false;
10189                         // simply scan ahead until we find a different texture or lightmap state
10190                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10191                                 ;
10192                 }
10193                 else
10194                 {
10195                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10196                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10197                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10198                         // simply scan ahead until we find a different texture or lightmap state
10199                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10200                                 ;
10201                 }
10202                 // render the range of surfaces
10203                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10204         }
10205         R_FrameData_ReturnToMark();
10206 }
10207
10208 float locboxvertex3f[6*4*3] =
10209 {
10210         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10211         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10212         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10213         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10214         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10215         1,0,0, 0,0,0, 0,1,0, 1,1,0
10216 };
10217
10218 unsigned short locboxelements[6*2*3] =
10219 {
10220          0, 1, 2, 0, 2, 3,
10221          4, 5, 6, 4, 6, 7,
10222          8, 9,10, 8,10,11,
10223         12,13,14, 12,14,15,
10224         16,17,18, 16,18,19,
10225         20,21,22, 20,22,23
10226 };
10227
10228 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10229 {
10230         int i, j;
10231         cl_locnode_t *loc = (cl_locnode_t *)ent;
10232         vec3_t mins, size;
10233         float vertex3f[6*4*3];
10234         CHECKGLERROR
10235         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10236         GL_DepthMask(false);
10237         GL_DepthRange(0, 1);
10238         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10239         GL_DepthTest(true);
10240         GL_CullFace(GL_NONE);
10241         R_EntityMatrix(&identitymatrix);
10242
10243 //      R_Mesh_ResetTextureState();
10244
10245         i = surfacelist[0];
10246         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10247                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10248                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10249                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10250
10251         if (VectorCompare(loc->mins, loc->maxs))
10252         {
10253                 VectorSet(size, 2, 2, 2);
10254                 VectorMA(loc->mins, -0.5f, size, mins);
10255         }
10256         else
10257         {
10258                 VectorCopy(loc->mins, mins);
10259                 VectorSubtract(loc->maxs, loc->mins, size);
10260         }
10261
10262         for (i = 0;i < 6*4*3;)
10263                 for (j = 0;j < 3;j++, i++)
10264                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10265
10266         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10267         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10268         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10269 }
10270
10271 void R_DrawLocs(void)
10272 {
10273         int index;
10274         cl_locnode_t *loc, *nearestloc;
10275         vec3_t center;
10276         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10277         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10278         {
10279                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10280                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10281         }
10282 }
10283
10284 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10285 {
10286         if (decalsystem->decals)
10287                 Mem_Free(decalsystem->decals);
10288         memset(decalsystem, 0, sizeof(*decalsystem));
10289 }
10290
10291 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)
10292 {
10293         tridecal_t *decal;
10294         tridecal_t *decals;
10295         int i;
10296
10297         // expand or initialize the system
10298         if (decalsystem->maxdecals <= decalsystem->numdecals)
10299         {
10300                 decalsystem_t old = *decalsystem;
10301                 qboolean useshortelements;
10302                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10303                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10304                 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)));
10305                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10306                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10307                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10308                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10309                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10310                 if (decalsystem->numdecals)
10311                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10312                 if (old.decals)
10313                         Mem_Free(old.decals);
10314                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10315                         decalsystem->element3i[i] = i;
10316                 if (useshortelements)
10317                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10318                                 decalsystem->element3s[i] = i;
10319         }
10320
10321         // grab a decal and search for another free slot for the next one
10322         decals = decalsystem->decals;
10323         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10324         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10325                 ;
10326         decalsystem->freedecal = i;
10327         if (decalsystem->numdecals <= i)
10328                 decalsystem->numdecals = i + 1;
10329
10330         // initialize the decal
10331         decal->lived = 0;
10332         decal->triangleindex = triangleindex;
10333         decal->surfaceindex = surfaceindex;
10334         decal->decalsequence = decalsequence;
10335         decal->color4f[0][0] = c0[0];
10336         decal->color4f[0][1] = c0[1];
10337         decal->color4f[0][2] = c0[2];
10338         decal->color4f[0][3] = 1;
10339         decal->color4f[1][0] = c1[0];
10340         decal->color4f[1][1] = c1[1];
10341         decal->color4f[1][2] = c1[2];
10342         decal->color4f[1][3] = 1;
10343         decal->color4f[2][0] = c2[0];
10344         decal->color4f[2][1] = c2[1];
10345         decal->color4f[2][2] = c2[2];
10346         decal->color4f[2][3] = 1;
10347         decal->vertex3f[0][0] = v0[0];
10348         decal->vertex3f[0][1] = v0[1];
10349         decal->vertex3f[0][2] = v0[2];
10350         decal->vertex3f[1][0] = v1[0];
10351         decal->vertex3f[1][1] = v1[1];
10352         decal->vertex3f[1][2] = v1[2];
10353         decal->vertex3f[2][0] = v2[0];
10354         decal->vertex3f[2][1] = v2[1];
10355         decal->vertex3f[2][2] = v2[2];
10356         decal->texcoord2f[0][0] = t0[0];
10357         decal->texcoord2f[0][1] = t0[1];
10358         decal->texcoord2f[1][0] = t1[0];
10359         decal->texcoord2f[1][1] = t1[1];
10360         decal->texcoord2f[2][0] = t2[0];
10361         decal->texcoord2f[2][1] = t2[1];
10362 }
10363
10364 extern cvar_t cl_decals_bias;
10365 extern cvar_t cl_decals_models;
10366 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10367 // baseparms, parms, temps
10368 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)
10369 {
10370         int cornerindex;
10371         int index;
10372         float v[9][3];
10373         const float *vertex3f;
10374         const float *normal3f;
10375         int numpoints;
10376         float points[2][9][3];
10377         float temp[3];
10378         float tc[9][2];
10379         float f;
10380         float c[9][4];
10381         const int *e;
10382
10383         e = rsurface.modelelement3i + 3*triangleindex;
10384
10385         vertex3f = rsurface.modelvertex3f;
10386         normal3f = rsurface.modelnormal3f;
10387
10388         if (normal3f)
10389         {
10390                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10391                 {
10392                         index = 3*e[cornerindex];
10393                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10394                 }
10395         }
10396         else
10397         {
10398                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10399                 {
10400                         index = 3*e[cornerindex];
10401                         VectorCopy(vertex3f + index, v[cornerindex]);
10402                 }
10403         }
10404
10405         // cull backfaces
10406         //TriangleNormal(v[0], v[1], v[2], normal);
10407         //if (DotProduct(normal, localnormal) < 0.0f)
10408         //      continue;
10409         // clip by each of the box planes formed from the projection matrix
10410         // if anything survives, we emit the decal
10411         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]);
10412         if (numpoints < 3)
10413                 return;
10414         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]);
10415         if (numpoints < 3)
10416                 return;
10417         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]);
10418         if (numpoints < 3)
10419                 return;
10420         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]);
10421         if (numpoints < 3)
10422                 return;
10423         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]);
10424         if (numpoints < 3)
10425                 return;
10426         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]);
10427         if (numpoints < 3)
10428                 return;
10429         // some part of the triangle survived, so we have to accept it...
10430         if (dynamic)
10431         {
10432                 // dynamic always uses the original triangle
10433                 numpoints = 3;
10434                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10435                 {
10436                         index = 3*e[cornerindex];
10437                         VectorCopy(vertex3f + index, v[cornerindex]);
10438                 }
10439         }
10440         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10441         {
10442                 // convert vertex positions to texcoords
10443                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10444                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10445                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10446                 // calculate distance fade from the projection origin
10447                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10448                 f = bound(0.0f, f, 1.0f);
10449                 c[cornerindex][0] = r * f;
10450                 c[cornerindex][1] = g * f;
10451                 c[cornerindex][2] = b * f;
10452                 c[cornerindex][3] = 1.0f;
10453                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10454         }
10455         if (dynamic)
10456                 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);
10457         else
10458                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10459                         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);
10460 }
10461 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)
10462 {
10463         matrix4x4_t projection;
10464         decalsystem_t *decalsystem;
10465         qboolean dynamic;
10466         dp_model_t *model;
10467         const msurface_t *surface;
10468         const msurface_t *surfaces;
10469         const int *surfacelist;
10470         const texture_t *texture;
10471         int numtriangles;
10472         int numsurfacelist;
10473         int surfacelistindex;
10474         int surfaceindex;
10475         int triangleindex;
10476         float localorigin[3];
10477         float localnormal[3];
10478         float localmins[3];
10479         float localmaxs[3];
10480         float localsize;
10481         //float normal[3];
10482         float planes[6][4];
10483         float angles[3];
10484         bih_t *bih;
10485         int bih_triangles_count;
10486         int bih_triangles[256];
10487         int bih_surfaces[256];
10488
10489         decalsystem = &ent->decalsystem;
10490         model = ent->model;
10491         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10492         {
10493                 R_DecalSystem_Reset(&ent->decalsystem);
10494                 return;
10495         }
10496
10497         if (!model->brush.data_leafs && !cl_decals_models.integer)
10498         {
10499                 if (decalsystem->model)
10500                         R_DecalSystem_Reset(decalsystem);
10501                 return;
10502         }
10503
10504         if (decalsystem->model != model)
10505                 R_DecalSystem_Reset(decalsystem);
10506         decalsystem->model = model;
10507
10508         RSurf_ActiveModelEntity(ent, true, false, false);
10509
10510         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10511         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10512         VectorNormalize(localnormal);
10513         localsize = worldsize*rsurface.inversematrixscale;
10514         localmins[0] = localorigin[0] - localsize;
10515         localmins[1] = localorigin[1] - localsize;
10516         localmins[2] = localorigin[2] - localsize;
10517         localmaxs[0] = localorigin[0] + localsize;
10518         localmaxs[1] = localorigin[1] + localsize;
10519         localmaxs[2] = localorigin[2] + localsize;
10520
10521         //VectorCopy(localnormal, planes[4]);
10522         //VectorVectors(planes[4], planes[2], planes[0]);
10523         AnglesFromVectors(angles, localnormal, NULL, false);
10524         AngleVectors(angles, planes[0], planes[2], planes[4]);
10525         VectorNegate(planes[0], planes[1]);
10526         VectorNegate(planes[2], planes[3]);
10527         VectorNegate(planes[4], planes[5]);
10528         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10529         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10530         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10531         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10532         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10533         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10534
10535 #if 1
10536 // works
10537 {
10538         matrix4x4_t forwardprojection;
10539         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10540         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10541 }
10542 #else
10543 // broken
10544 {
10545         float projectionvector[4][3];
10546         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10547         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10548         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10549         projectionvector[0][0] = planes[0][0] * ilocalsize;
10550         projectionvector[0][1] = planes[1][0] * ilocalsize;
10551         projectionvector[0][2] = planes[2][0] * ilocalsize;
10552         projectionvector[1][0] = planes[0][1] * ilocalsize;
10553         projectionvector[1][1] = planes[1][1] * ilocalsize;
10554         projectionvector[1][2] = planes[2][1] * ilocalsize;
10555         projectionvector[2][0] = planes[0][2] * ilocalsize;
10556         projectionvector[2][1] = planes[1][2] * ilocalsize;
10557         projectionvector[2][2] = planes[2][2] * ilocalsize;
10558         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10559         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10560         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10561         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10562 }
10563 #endif
10564
10565         dynamic = model->surfmesh.isanimated;
10566         numsurfacelist = model->nummodelsurfaces;
10567         surfacelist = model->sortedmodelsurfaces;
10568         surfaces = model->data_surfaces;
10569
10570         bih = NULL;
10571         bih_triangles_count = -1;
10572         if(!dynamic)
10573         {
10574                 if(model->render_bih.numleafs)
10575                         bih = &model->render_bih;
10576                 else if(model->collision_bih.numleafs)
10577                         bih = &model->collision_bih;
10578         }
10579         if(bih)
10580                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10581         if(bih_triangles_count == 0)
10582                 return;
10583         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10584                 return;
10585         if(bih_triangles_count > 0)
10586         {
10587                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10588                 {
10589                         surfaceindex = bih_surfaces[triangleindex];
10590                         surface = surfaces + surfaceindex;
10591                         texture = surface->texture;
10592                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10593                                 continue;
10594                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10595                                 continue;
10596                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10597                 }
10598         }
10599         else
10600         {
10601                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10602                 {
10603                         surfaceindex = surfacelist[surfacelistindex];
10604                         surface = surfaces + surfaceindex;
10605                         // check cull box first because it rejects more than any other check
10606                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10607                                 continue;
10608                         // skip transparent surfaces
10609                         texture = surface->texture;
10610                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10611                                 continue;
10612                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10613                                 continue;
10614                         numtriangles = surface->num_triangles;
10615                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10616                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10617                 }
10618         }
10619 }
10620
10621 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10622 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)
10623 {
10624         int renderentityindex;
10625         float worldmins[3];
10626         float worldmaxs[3];
10627         entity_render_t *ent;
10628
10629         if (!cl_decals_newsystem.integer)
10630                 return;
10631
10632         worldmins[0] = worldorigin[0] - worldsize;
10633         worldmins[1] = worldorigin[1] - worldsize;
10634         worldmins[2] = worldorigin[2] - worldsize;
10635         worldmaxs[0] = worldorigin[0] + worldsize;
10636         worldmaxs[1] = worldorigin[1] + worldsize;
10637         worldmaxs[2] = worldorigin[2] + worldsize;
10638
10639         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10640
10641         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10642         {
10643                 ent = r_refdef.scene.entities[renderentityindex];
10644                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10645                         continue;
10646
10647                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10648         }
10649 }
10650
10651 typedef struct r_decalsystem_splatqueue_s
10652 {
10653         vec3_t worldorigin;
10654         vec3_t worldnormal;
10655         float color[4];
10656         float tcrange[4];
10657         float worldsize;
10658         int decalsequence;
10659 }
10660 r_decalsystem_splatqueue_t;
10661
10662 int r_decalsystem_numqueued = 0;
10663 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10664
10665 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)
10666 {
10667         r_decalsystem_splatqueue_t *queue;
10668
10669         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10670                 return;
10671
10672         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10673         VectorCopy(worldorigin, queue->worldorigin);
10674         VectorCopy(worldnormal, queue->worldnormal);
10675         Vector4Set(queue->color, r, g, b, a);
10676         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10677         queue->worldsize = worldsize;
10678         queue->decalsequence = cl.decalsequence++;
10679 }
10680
10681 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10682 {
10683         int i;
10684         r_decalsystem_splatqueue_t *queue;
10685
10686         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10687                 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);
10688         r_decalsystem_numqueued = 0;
10689 }
10690
10691 extern cvar_t cl_decals_max;
10692 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10693 {
10694         int i;
10695         decalsystem_t *decalsystem = &ent->decalsystem;
10696         int numdecals;
10697         int killsequence;
10698         tridecal_t *decal;
10699         float frametime;
10700         float lifetime;
10701
10702         if (!decalsystem->numdecals)
10703                 return;
10704
10705         if (r_showsurfaces.integer)
10706                 return;
10707
10708         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10709         {
10710                 R_DecalSystem_Reset(decalsystem);
10711                 return;
10712         }
10713
10714         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10715         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10716
10717         if (decalsystem->lastupdatetime)
10718                 frametime = (cl.time - decalsystem->lastupdatetime);
10719         else
10720                 frametime = 0;
10721         decalsystem->lastupdatetime = cl.time;
10722         decal = decalsystem->decals;
10723         numdecals = decalsystem->numdecals;
10724
10725         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10726         {
10727                 if (decal->color4f[0][3])
10728                 {
10729                         decal->lived += frametime;
10730                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10731                         {
10732                                 memset(decal, 0, sizeof(*decal));
10733                                 if (decalsystem->freedecal > i)
10734                                         decalsystem->freedecal = i;
10735                         }
10736                 }
10737         }
10738         decal = decalsystem->decals;
10739         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10740                 numdecals--;
10741
10742         // collapse the array by shuffling the tail decals into the gaps
10743         for (;;)
10744         {
10745                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10746                         decalsystem->freedecal++;
10747                 if (decalsystem->freedecal == numdecals)
10748                         break;
10749                 decal[decalsystem->freedecal] = decal[--numdecals];
10750         }
10751
10752         decalsystem->numdecals = numdecals;
10753
10754         if (numdecals <= 0)
10755         {
10756                 // if there are no decals left, reset decalsystem
10757                 R_DecalSystem_Reset(decalsystem);
10758         }
10759 }
10760
10761 extern skinframe_t *decalskinframe;
10762 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10763 {
10764         int i;
10765         decalsystem_t *decalsystem = &ent->decalsystem;
10766         int numdecals;
10767         tridecal_t *decal;
10768         float faderate;
10769         float alpha;
10770         float *v3f;
10771         float *c4f;
10772         float *t2f;
10773         const int *e;
10774         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10775         int numtris = 0;
10776
10777         numdecals = decalsystem->numdecals;
10778         if (!numdecals)
10779                 return;
10780
10781         if (r_showsurfaces.integer)
10782                 return;
10783
10784         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10785         {
10786                 R_DecalSystem_Reset(decalsystem);
10787                 return;
10788         }
10789
10790         // if the model is static it doesn't matter what value we give for
10791         // wantnormals and wanttangents, so this logic uses only rules applicable
10792         // to a model, knowing that they are meaningless otherwise
10793         if (ent == r_refdef.scene.worldentity)
10794                 RSurf_ActiveWorldEntity();
10795         else
10796                 RSurf_ActiveModelEntity(ent, false, false, false);
10797
10798         decalsystem->lastupdatetime = cl.time;
10799         decal = decalsystem->decals;
10800
10801         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10802
10803         // update vertex positions for animated models
10804         v3f = decalsystem->vertex3f;
10805         c4f = decalsystem->color4f;
10806         t2f = decalsystem->texcoord2f;
10807         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10808         {
10809                 if (!decal->color4f[0][3])
10810                         continue;
10811
10812                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10813                         continue;
10814
10815                 // update color values for fading decals
10816                 if (decal->lived >= cl_decals_time.value)
10817                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10818                 else
10819                         alpha = 1.0f;
10820
10821                 c4f[ 0] = decal->color4f[0][0] * alpha;
10822                 c4f[ 1] = decal->color4f[0][1] * alpha;
10823                 c4f[ 2] = decal->color4f[0][2] * alpha;
10824                 c4f[ 3] = 1;
10825                 c4f[ 4] = decal->color4f[1][0] * alpha;
10826                 c4f[ 5] = decal->color4f[1][1] * alpha;
10827                 c4f[ 6] = decal->color4f[1][2] * alpha;
10828                 c4f[ 7] = 1;
10829                 c4f[ 8] = decal->color4f[2][0] * alpha;
10830                 c4f[ 9] = decal->color4f[2][1] * alpha;
10831                 c4f[10] = decal->color4f[2][2] * alpha;
10832                 c4f[11] = 1;
10833
10834                 t2f[0] = decal->texcoord2f[0][0];
10835                 t2f[1] = decal->texcoord2f[0][1];
10836                 t2f[2] = decal->texcoord2f[1][0];
10837                 t2f[3] = decal->texcoord2f[1][1];
10838                 t2f[4] = decal->texcoord2f[2][0];
10839                 t2f[5] = decal->texcoord2f[2][1];
10840
10841                 // update vertex positions for animated models
10842                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10843                 {
10844                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10845                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10846                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10847                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10848                 }
10849                 else
10850                 {
10851                         VectorCopy(decal->vertex3f[0], v3f);
10852                         VectorCopy(decal->vertex3f[1], v3f + 3);
10853                         VectorCopy(decal->vertex3f[2], v3f + 6);
10854                 }
10855
10856                 if (r_refdef.fogenabled)
10857                 {
10858                         alpha = RSurf_FogVertex(v3f);
10859                         VectorScale(c4f, alpha, c4f);
10860                         alpha = RSurf_FogVertex(v3f + 3);
10861                         VectorScale(c4f + 4, alpha, c4f + 4);
10862                         alpha = RSurf_FogVertex(v3f + 6);
10863                         VectorScale(c4f + 8, alpha, c4f + 8);
10864                 }
10865
10866                 v3f += 9;
10867                 c4f += 12;
10868                 t2f += 6;
10869                 numtris++;
10870         }
10871
10872         if (numtris > 0)
10873         {
10874                 r_refdef.stats.drawndecals += numtris;
10875
10876                 // now render the decals all at once
10877                 // (this assumes they all use one particle font texture!)
10878                 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);
10879 //              R_Mesh_ResetTextureState();
10880                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10881                 GL_DepthMask(false);
10882                 GL_DepthRange(0, 1);
10883                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10884                 GL_DepthTest(true);
10885                 GL_CullFace(GL_NONE);
10886                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10887                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10888                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10889         }
10890 }
10891
10892 static void R_DrawModelDecals(void)
10893 {
10894         int i, numdecals;
10895
10896         // fade faster when there are too many decals
10897         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10898         for (i = 0;i < r_refdef.scene.numentities;i++)
10899                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10900
10901         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10902         for (i = 0;i < r_refdef.scene.numentities;i++)
10903                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10904                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10905
10906         R_DecalSystem_ApplySplatEntitiesQueue();
10907
10908         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10909         for (i = 0;i < r_refdef.scene.numentities;i++)
10910                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10911
10912         r_refdef.stats.totaldecals += numdecals;
10913
10914         if (r_showsurfaces.integer)
10915                 return;
10916
10917         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10918
10919         for (i = 0;i < r_refdef.scene.numentities;i++)
10920         {
10921                 if (!r_refdef.viewcache.entityvisible[i])
10922                         continue;
10923                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10924                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10925         }
10926 }
10927
10928 extern cvar_t mod_collision_bih;
10929 void R_DrawDebugModel(void)
10930 {
10931         entity_render_t *ent = rsurface.entity;
10932         int i, j, k, l, flagsmask;
10933         const msurface_t *surface;
10934         dp_model_t *model = ent->model;
10935         vec3_t v;
10936
10937         switch(vid.renderpath)
10938         {
10939         case RENDERPATH_GL11:
10940         case RENDERPATH_GL13:
10941         case RENDERPATH_GL20:
10942                 break;
10943         case RENDERPATH_D3D9:
10944                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10945                 return;
10946         case RENDERPATH_D3D10:
10947                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10948                 return;
10949         case RENDERPATH_D3D11:
10950                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10951                 return;
10952         case RENDERPATH_SOFT:
10953                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10954                 return;
10955         case RENDERPATH_GLES2:
10956                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10957                 return;
10958         }
10959
10960         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10961
10962 //      R_Mesh_ResetTextureState();
10963         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10964         GL_DepthRange(0, 1);
10965         GL_DepthTest(!r_showdisabledepthtest.integer);
10966         GL_DepthMask(false);
10967         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10968
10969         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10970         {
10971                 int triangleindex;
10972                 int bihleafindex;
10973                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10974                 const q3mbrush_t *brush;
10975                 const bih_t *bih = &model->collision_bih;
10976                 const bih_leaf_t *bihleaf;
10977                 float vertex3f[3][3];
10978                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10979                 cullbox = false;
10980                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10981                 {
10982                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10983                                 continue;
10984                         switch (bihleaf->type)
10985                         {
10986                         case BIH_BRUSH:
10987                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10988                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10989                                 {
10990                                         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);
10991                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10992                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10993                                 }
10994                                 break;
10995                         case BIH_COLLISIONTRIANGLE:
10996                                 triangleindex = bihleaf->itemindex;
10997                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10998                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10999                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11000                                 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);
11001                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11002                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11003                                 break;
11004                         case BIH_RENDERTRIANGLE:
11005                                 triangleindex = bihleaf->itemindex;
11006                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11007                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11008                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11009                                 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);
11010                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11011                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11012                                 break;
11013                         }
11014                 }
11015         }
11016
11017         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11018
11019         if (r_showtris.integer || (r_shownormals.value != 0))
11020         {
11021                 if (r_showdisabledepthtest.integer)
11022                 {
11023                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11024                         GL_DepthMask(false);
11025                 }
11026                 else
11027                 {
11028                         GL_BlendFunc(GL_ONE, GL_ZERO);
11029                         GL_DepthMask(true);
11030                 }
11031                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11032                 {
11033                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11034                                 continue;
11035                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11036                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11037                         {
11038                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11039                                 if (r_showtris.value > 0)
11040                                 {
11041                                         if (!rsurface.texture->currentlayers->depthmask)
11042                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11043                                         else if (ent == r_refdef.scene.worldentity)
11044                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11045                                         else
11046                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11047                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11048                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11049                                         RSurf_DrawBatch();
11050                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11051                                         CHECKGLERROR
11052                                 }
11053                                 if (r_shownormals.value < 0)
11054                                 {
11055                                         qglBegin(GL_LINES);
11056                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11057                                         {
11058                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11059                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11060                                                 qglVertex3f(v[0], v[1], v[2]);
11061                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11062                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11063                                                 qglVertex3f(v[0], v[1], v[2]);
11064                                         }
11065                                         qglEnd();
11066                                         CHECKGLERROR
11067                                 }
11068                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11069                                 {
11070                                         qglBegin(GL_LINES);
11071                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11072                                         {
11073                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11074                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11075                                                 qglVertex3f(v[0], v[1], v[2]);
11076                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11077                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11078                                                 qglVertex3f(v[0], v[1], v[2]);
11079                                         }
11080                                         qglEnd();
11081                                         CHECKGLERROR
11082                                         qglBegin(GL_LINES);
11083                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11084                                         {
11085                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11086                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11087                                                 qglVertex3f(v[0], v[1], v[2]);
11088                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11089                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11090                                                 qglVertex3f(v[0], v[1], v[2]);
11091                                         }
11092                                         qglEnd();
11093                                         CHECKGLERROR
11094                                         qglBegin(GL_LINES);
11095                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11096                                         {
11097                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11098                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11099                                                 qglVertex3f(v[0], v[1], v[2]);
11100                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11101                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11102                                                 qglVertex3f(v[0], v[1], v[2]);
11103                                         }
11104                                         qglEnd();
11105                                         CHECKGLERROR
11106                                 }
11107                         }
11108                 }
11109                 rsurface.texture = NULL;
11110         }
11111 }
11112
11113 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11114 int r_maxsurfacelist = 0;
11115 const msurface_t **r_surfacelist = NULL;
11116 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11117 {
11118         int i, j, endj, flagsmask;
11119         dp_model_t *model = r_refdef.scene.worldmodel;
11120         msurface_t *surfaces;
11121         unsigned char *update;
11122         int numsurfacelist = 0;
11123         if (model == NULL)
11124                 return;
11125
11126         if (r_maxsurfacelist < model->num_surfaces)
11127         {
11128                 r_maxsurfacelist = model->num_surfaces;
11129                 if (r_surfacelist)
11130                         Mem_Free((msurface_t**)r_surfacelist);
11131                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11132         }
11133
11134         RSurf_ActiveWorldEntity();
11135
11136         surfaces = model->data_surfaces;
11137         update = model->brushq1.lightmapupdateflags;
11138
11139         // update light styles on this submodel
11140         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11141         {
11142                 model_brush_lightstyleinfo_t *style;
11143                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11144                 {
11145                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11146                         {
11147                                 int *list = style->surfacelist;
11148                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11149                                 for (j = 0;j < style->numsurfaces;j++)
11150                                         update[list[j]] = true;
11151                         }
11152                 }
11153         }
11154
11155         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11156
11157         if (debug)
11158         {
11159                 R_DrawDebugModel();
11160                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11161                 return;
11162         }
11163
11164         rsurface.lightmaptexture = NULL;
11165         rsurface.deluxemaptexture = NULL;
11166         rsurface.uselightmaptexture = false;
11167         rsurface.texture = NULL;
11168         rsurface.rtlight = NULL;
11169         numsurfacelist = 0;
11170         // add visible surfaces to draw list
11171         for (i = 0;i < model->nummodelsurfaces;i++)
11172         {
11173                 j = model->sortedmodelsurfaces[i];
11174                 if (r_refdef.viewcache.world_surfacevisible[j])
11175                         r_surfacelist[numsurfacelist++] = surfaces + j;
11176         }
11177         // update lightmaps if needed
11178         if (model->brushq1.firstrender)
11179         {
11180                 model->brushq1.firstrender = false;
11181                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11182                         if (update[j])
11183                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11184         }
11185         else if (update)
11186         {
11187                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11188                         if (r_refdef.viewcache.world_surfacevisible[j])
11189                                 if (update[j])
11190                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11191         }
11192         // don't do anything if there were no surfaces
11193         if (!numsurfacelist)
11194         {
11195                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11196                 return;
11197         }
11198         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11199
11200         // add to stats if desired
11201         if (r_speeds.integer && !skysurfaces && !depthonly)
11202         {
11203                 r_refdef.stats.world_surfaces += numsurfacelist;
11204                 for (j = 0;j < numsurfacelist;j++)
11205                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11206         }
11207
11208         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11209 }
11210
11211 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11212 {
11213         int i, j, endj, flagsmask;
11214         dp_model_t *model = ent->model;
11215         msurface_t *surfaces;
11216         unsigned char *update;
11217         int numsurfacelist = 0;
11218         if (model == NULL)
11219                 return;
11220
11221         if (r_maxsurfacelist < model->num_surfaces)
11222         {
11223                 r_maxsurfacelist = model->num_surfaces;
11224                 if (r_surfacelist)
11225                         Mem_Free((msurface_t **)r_surfacelist);
11226                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11227         }
11228
11229         // if the model is static it doesn't matter what value we give for
11230         // wantnormals and wanttangents, so this logic uses only rules applicable
11231         // to a model, knowing that they are meaningless otherwise
11232         if (ent == r_refdef.scene.worldentity)
11233                 RSurf_ActiveWorldEntity();
11234         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11235                 RSurf_ActiveModelEntity(ent, false, false, false);
11236         else if (prepass)
11237                 RSurf_ActiveModelEntity(ent, true, true, true);
11238         else if (depthonly)
11239         {
11240                 switch (vid.renderpath)
11241                 {
11242                 case RENDERPATH_GL20:
11243                 case RENDERPATH_D3D9:
11244                 case RENDERPATH_D3D10:
11245                 case RENDERPATH_D3D11:
11246                 case RENDERPATH_SOFT:
11247                 case RENDERPATH_GLES2:
11248                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11249                         break;
11250                 case RENDERPATH_GL13:
11251                 case RENDERPATH_GL11:
11252                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11253                         break;
11254                 }
11255         }
11256         else
11257         {
11258                 switch (vid.renderpath)
11259                 {
11260                 case RENDERPATH_GL20:
11261                 case RENDERPATH_D3D9:
11262                 case RENDERPATH_D3D10:
11263                 case RENDERPATH_D3D11:
11264                 case RENDERPATH_SOFT:
11265                 case RENDERPATH_GLES2:
11266                         RSurf_ActiveModelEntity(ent, true, true, false);
11267                         break;
11268                 case RENDERPATH_GL13:
11269                 case RENDERPATH_GL11:
11270                         RSurf_ActiveModelEntity(ent, true, false, false);
11271                         break;
11272                 }
11273         }
11274
11275         surfaces = model->data_surfaces;
11276         update = model->brushq1.lightmapupdateflags;
11277
11278         // update light styles
11279         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11280         {
11281                 model_brush_lightstyleinfo_t *style;
11282                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11283                 {
11284                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11285                         {
11286                                 int *list = style->surfacelist;
11287                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11288                                 for (j = 0;j < style->numsurfaces;j++)
11289                                         update[list[j]] = true;
11290                         }
11291                 }
11292         }
11293
11294         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11295
11296         if (debug)
11297         {
11298                 R_DrawDebugModel();
11299                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11300                 return;
11301         }
11302
11303         rsurface.lightmaptexture = NULL;
11304         rsurface.deluxemaptexture = NULL;
11305         rsurface.uselightmaptexture = false;
11306         rsurface.texture = NULL;
11307         rsurface.rtlight = NULL;
11308         numsurfacelist = 0;
11309         // add visible surfaces to draw list
11310         for (i = 0;i < model->nummodelsurfaces;i++)
11311                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11312         // don't do anything if there were no surfaces
11313         if (!numsurfacelist)
11314         {
11315                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11316                 return;
11317         }
11318         // update lightmaps if needed
11319         if (update)
11320         {
11321                 int updated = 0;
11322                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11323                 {
11324                         if (update[j])
11325                         {
11326                                 updated++;
11327                                 R_BuildLightMap(ent, surfaces + j);
11328                         }
11329                 }
11330         }
11331         if (update)
11332                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11333                         if (update[j])
11334                                 R_BuildLightMap(ent, surfaces + j);
11335         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11336
11337         // add to stats if desired
11338         if (r_speeds.integer && !skysurfaces && !depthonly)
11339         {
11340                 r_refdef.stats.entities_surfaces += numsurfacelist;
11341                 for (j = 0;j < numsurfacelist;j++)
11342                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11343         }
11344
11345         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11346 }
11347
11348 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11349 {
11350         static texture_t texture;
11351         static msurface_t surface;
11352         const msurface_t *surfacelist = &surface;
11353
11354         // fake enough texture and surface state to render this geometry
11355
11356         texture.update_lastrenderframe = -1; // regenerate this texture
11357         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11358         texture.currentskinframe = skinframe;
11359         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11360         texture.offsetmapping = OFFSETMAPPING_OFF;
11361         texture.offsetscale = 1;
11362         texture.specularscalemod = 1;
11363         texture.specularpowermod = 1;
11364
11365         surface.texture = &texture;
11366         surface.num_triangles = numtriangles;
11367         surface.num_firsttriangle = firsttriangle;
11368         surface.num_vertices = numvertices;
11369         surface.num_firstvertex = firstvertex;
11370
11371         // now render it
11372         rsurface.texture = R_GetCurrentTexture(surface.texture);
11373         rsurface.lightmaptexture = NULL;
11374         rsurface.deluxemaptexture = NULL;
11375         rsurface.uselightmaptexture = false;
11376         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11377 }
11378
11379 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)
11380 {
11381         static msurface_t surface;
11382         const msurface_t *surfacelist = &surface;
11383
11384         // fake enough texture and surface state to render this geometry
11385         surface.texture = texture;
11386         surface.num_triangles = numtriangles;
11387         surface.num_firsttriangle = firsttriangle;
11388         surface.num_vertices = numvertices;
11389         surface.num_firstvertex = firstvertex;
11390
11391         // now render it
11392         rsurface.texture = R_GetCurrentTexture(surface.texture);
11393         rsurface.lightmaptexture = NULL;
11394         rsurface.deluxemaptexture = NULL;
11395         rsurface.uselightmaptexture = false;
11396         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11397 }