]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rmain.c
reworked progs loading so that entvars_t and globalvars_t are no longer
[xonotic/darkplaces.git] / gl_rmain.c
index 30624785ba9cd55a43329f1324c6e6c8fbaa6eeb..8574aeb2db3c3dc43ed43ee2915348e17d72a800 100644 (file)
@@ -70,6 +70,10 @@ cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables
 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
+cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
+cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
+cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
+cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
 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)"};
 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
@@ -115,8 +119,11 @@ cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset",
 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
+cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
 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"};
+cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
+cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
 
 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
@@ -130,19 +137,25 @@ cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the re
 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)"};
 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"};
 
-cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
-cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
-cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
-cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
-cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
-
 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
 
+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"};
+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"};
+cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
+cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
+cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
+cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
+cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
+cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
+
 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)"};
 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
+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)"};
 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
+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)"};
+cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
 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)"};
@@ -160,6 +173,7 @@ cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier"
 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
+cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
 
 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
@@ -171,13 +185,19 @@ cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright t
 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
-cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
+cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
 
 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
-cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
+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)"};
+cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
+cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
+cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
+cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
+cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
+cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
 
 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"};
 
@@ -186,18 +206,12 @@ cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces
 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
 
 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
-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"};
-cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
-cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
-cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
-cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
-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)"};
-cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
-cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
 
 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
 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"};
 
+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."};
+
 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)"};
 
 extern cvar_t v_glslgamma;
@@ -211,6 +225,13 @@ static struct r_bloomstate_s
 
        int bloomwidth, bloomheight;
 
+       textype_t texturetype;
+       int viewfbo; // used to check if r_viewfbo cvar has changed
+
+       int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
+       rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
+       rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
+
        int screentexturewidth, screentextureheight;
        rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
 
@@ -254,7 +275,7 @@ typedef struct cubemapinfo_s
 cubemapinfo_t;
 
 int r_texture_numcubemaps;
-cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
+cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
 
 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
 unsigned int r_numqueries;
@@ -506,8 +527,8 @@ static void R_BuildFogTexture(void)
        }
        if (r_texture_fogattenuation)
        {
-               R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
-               //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
+               R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
+               //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
        }
        else
        {
@@ -587,2741 +608,14 @@ static void R_BuildFogHeightTexture(void)
 //=======================================================================================================================================================
 
 static const char *builtinshaderstring =
-"// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
-"// written by Forest 'LordHavoc' Hale\n"
-"// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
-"\n"
-"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
-"# define USEFOG\n"
-"#endif\n"
-"#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
-"#define USELIGHTMAP\n"
-"#endif\n"
-"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
-"#define USEEYEVECTOR\n"
-"#endif\n"
-"\n"
-"#ifdef USESHADOWMAP2D\n"
-"# ifdef GL_EXT_gpu_shader4\n"
-"#   extension GL_EXT_gpu_shader4 : enable\n"
-"# endif\n"
-"# ifdef GL_ARB_texture_gather\n"
-"#   extension GL_ARB_texture_gather : enable\n"
-"# else\n"
-"#   ifdef GL_AMD_texture_texture4\n"
-"#     extension GL_AMD_texture_texture4 : enable\n"
-"#   endif\n"
-"# endif\n"
-"#endif\n"
-"\n"
-"//#ifdef USESHADOWSAMPLER\n"
-"//# extension GL_ARB_shadow : enable\n"
-"//#endif\n"
-"\n"
-"//#ifdef __GLSL_CG_DATA_TYPES\n"
-"//# define myhalf half\n"
-"//# define myhalf2 half2\n"
-"//# define myhalf3 half3\n"
-"//# define myhalf4 half4\n"
-"//#else\n"
-"# define myhalf float\n"
-"# define myhalf2 vec2\n"
-"# define myhalf3 vec3\n"
-"# define myhalf4 vec4\n"
-"//#endif\n"
-"\n"
-"#ifdef VERTEX_SHADER\n"
-"uniform mat4 ModelViewProjectionMatrix;\n"
-"#endif\n"
-"\n"
-"#ifdef MODE_DEPTH_OR_SHADOW\n"
-"#ifdef VERTEX_SHADER\n"
-"void main(void)\n"
-"{\n"
-"      gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
-"}\n"
-"#endif\n"
-"#else // !MODE_DEPTH_ORSHADOW\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_SHOWDEPTH\n"
-"#ifdef VERTEX_SHADER\n"
-"void main(void)\n"
-"{\n"
-"      gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
-"      gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"void main(void)\n"
-"{\n"
-"      gl_FragColor = gl_Color;\n"
-"}\n"
-"#endif\n"
-"#else // !MODE_SHOWDEPTH\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_POSTPROCESS\n"
-"varying vec2 TexCoord1;\n"
-"varying vec2 TexCoord2;\n"
-"\n"
-"#ifdef VERTEX_SHADER\n"
-"void main(void)\n"
-"{\n"
-"      gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
-"      TexCoord1 = gl_MultiTexCoord0.xy;\n"
-"#ifdef USEBLOOM\n"
-"      TexCoord2 = gl_MultiTexCoord4.xy;\n"
-"#endif\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"uniform sampler2D Texture_First;\n"
-"#ifdef USEBLOOM\n"
-"uniform sampler2D Texture_Second;\n"
-"uniform vec4 BloomColorSubtract;\n"
-"#endif\n"
-"#ifdef USEGAMMARAMPS\n"
-"uniform sampler2D Texture_GammaRamps;\n"
-"#endif\n"
-"#ifdef USESATURATION\n"
-"uniform float Saturation;\n"
-"#endif\n"
-"#ifdef USEVIEWTINT\n"
-"uniform vec4 ViewTintColor;\n"
-"#endif\n"
-"//uncomment these if you want to use them:\n"
-"uniform vec4 UserVec1;\n"
-"uniform vec4 UserVec2;\n"
-"// uniform vec4 UserVec3;\n"
-"// uniform vec4 UserVec4;\n"
-"// uniform float ClientTime;\n"
-"uniform vec2 PixelSize;\n"
-"void main(void)\n"
-"{\n"
-"      gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
-"#ifdef USEBLOOM\n"
-"      gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
-"#endif\n"
-"#ifdef USEVIEWTINT\n"
-"      gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
-"#endif\n"
-"\n"
-"#ifdef USEPOSTPROCESSING\n"
-"// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
-"// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
-"      float sobel = 1.0;\n"
-"      // vec2 ts = textureSize(Texture_First, 0);\n"
-"      // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
-"      vec2 px = PixelSize;\n"
-"      vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
-"      vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
-"      vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
-"      vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
-"      vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
-"      vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
-"      vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
-"      vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
-"      vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
-"      vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
-"      vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
-"      vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
-"      float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
-"      float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
-"      float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
-"      float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
-"      float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
-"      float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
-"      float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
-"      float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
-"      float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
-"      float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
-"      float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
-"      float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
-"      sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
-"      gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
-"      gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
-"      gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
-"      gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
-"      gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
-"      gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
-"      gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
-"#endif\n"
-"\n"
-"#ifdef USESATURATION\n"
-"      //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
-"      float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
-"      // 'vampire sight' effect, wheres red is compensated\n"
-"      #ifdef SATURATION_REDCOMPENSATE\n"
-"              float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
-"              gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
-"              gl_FragColor.r += rboost;\n"
-"      #else\n"
-"              // normal desaturation\n"
-"              //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
-"              gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
-"      #endif\n"
-"#endif\n"
-"\n"
-"#ifdef USEGAMMARAMPS\n"
-"      gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
-"      gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
-"      gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
-"#endif\n"
-"}\n"
-"#endif\n"
-"#else // !MODE_POSTPROCESS\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_GENERIC\n"
-"#ifdef USEDIFFUSE\n"
-"varying vec2 TexCoord1;\n"
-"#endif\n"
-"#ifdef USESPECULAR\n"
-"varying vec2 TexCoord2;\n"
-"#endif\n"
-"#ifdef VERTEX_SHADER\n"
-"void main(void)\n"
-"{\n"
-"      gl_FrontColor = gl_Color;\n"
-"#ifdef USEDIFFUSE\n"
-"      TexCoord1 = gl_MultiTexCoord0.xy;\n"
-"#endif\n"
-"#ifdef USESPECULAR\n"
-"      TexCoord2 = gl_MultiTexCoord1.xy;\n"
-"#endif\n"
-"      gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"#ifdef USEDIFFUSE\n"
-"uniform sampler2D Texture_First;\n"
-"#endif\n"
-"#ifdef USESPECULAR\n"
-"uniform sampler2D Texture_Second;\n"
-"#endif\n"
-"\n"
-"void main(void)\n"
-"{\n"
-"#ifdef USEVIEWTINT\n"
-"      gl_FragColor = gl_Color;\n"
-"#else\n"
-"      gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
-"#endif\n"
-"#ifdef USEDIFFUSE\n"
-"      gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
-"#endif\n"
-"\n"
-"#ifdef USESPECULAR\n"
-"      vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
-"# ifdef USECOLORMAPPING\n"
-"      gl_FragColor *= tex2;\n"
-"# endif\n"
-"# ifdef USEGLOW\n"
-"      gl_FragColor += tex2;\n"
-"# endif\n"
-"# ifdef USEVERTEXTEXTUREBLEND\n"
-"      gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
-"# endif\n"
-"#endif\n"
-"}\n"
-"#endif\n"
-"#else // !MODE_GENERIC\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_BLOOMBLUR\n"
-"varying TexCoord;\n"
-"#ifdef VERTEX_SHADER\n"
-"void main(void)\n"
-"{\n"
-"      gl_FrontColor = gl_Color;\n"
-"      TexCoord = gl_MultiTexCoord0.xy;\n"
-"      gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"uniform sampler2D Texture_First;\n"
-"uniform vec4 BloomBlur_Parameters;\n"
-"\n"
-"void main(void)\n"
-"{\n"
-"      int i;\n"
-"      vec2 tc = TexCoord;\n"
-"      vec3 color = texture2D(Texture_First, tc).rgb;\n"
-"      tc += BloomBlur_Parameters.xy;\n"
-"      for (i = 1;i < SAMPLES;i++)\n"
-"      {\n"
-"              color += texture2D(Texture_First, tc).rgb;\n"
-"              tc += BloomBlur_Parameters.xy;\n"
-"      }\n"
-"      gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
-"}\n"
-"#endif\n"
-"#else // !MODE_BLOOMBLUR\n"
-"#ifdef MODE_REFRACTION\n"
-"varying vec2 TexCoord;\n"
-"varying vec4 ModelViewProjectionPosition;\n"
-"uniform mat4 TexMatrix;\n"
-"#ifdef VERTEX_SHADER\n"
-"\n"
-"void main(void)\n"
-"{\n"
-"      TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
-"      gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
-"      ModelViewProjectionPosition = gl_Position;\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"uniform sampler2D Texture_Normal;\n"
-"uniform sampler2D Texture_Refraction;\n"
-"uniform sampler2D Texture_Reflection;\n"
-"\n"
-"uniform vec4 DistortScaleRefractReflect;\n"
-"uniform vec4 ScreenScaleRefractReflect;\n"
-"uniform vec4 ScreenCenterRefractReflect;\n"
-"uniform vec4 RefractColor;\n"
-"uniform vec4 ReflectColor;\n"
-"uniform float ReflectFactor;\n"
-"uniform float ReflectOffset;\n"
-"\n"
-"void main(void)\n"
-"{\n"
-"      vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
-"      //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
-"      vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
-"      vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
-"      // FIXME temporary hack to detect the case that the reflection\n"
-"      // gets blackened at edges due to leaving the area that contains actual\n"
-"      // content.\n"
-"      // Remove this 'ack once we have a better way to stop this thing from\n"
-"      // 'appening.\n"
-"      float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
-"      ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
-"      gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
-"}\n"
-"#endif\n"
-"#else // !MODE_REFRACTION\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_WATER\n"
-"varying vec2 TexCoord;\n"
-"varying vec3 EyeVector;\n"
-"varying vec4 ModelViewProjectionPosition;\n"
-"#ifdef VERTEX_SHADER\n"
-"uniform vec3 EyePosition;\n"
-"uniform mat4 TexMatrix;\n"
-"\n"
-"void main(void)\n"
-"{\n"
-"      TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
-"      vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
-"      EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
-"      EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
-"      EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
-"      gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
-"      ModelViewProjectionPosition = gl_Position;\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"uniform sampler2D Texture_Normal;\n"
-"uniform sampler2D Texture_Refraction;\n"
-"uniform sampler2D Texture_Reflection;\n"
-"\n"
-"uniform vec4 DistortScaleRefractReflect;\n"
-"uniform vec4 ScreenScaleRefractReflect;\n"
-"uniform vec4 ScreenCenterRefractReflect;\n"
-"uniform vec4 RefractColor;\n"
-"uniform vec4 ReflectColor;\n"
-"uniform float ReflectFactor;\n"
-"uniform float ReflectOffset;\n"
-"uniform float ClientTime;\n"
-"#ifdef USENORMALMAPSCROLLBLEND\n"
-"uniform vec2 NormalmapScrollBlend;\n"
-"#endif\n"
-"\n"
-"void main(void)\n"
-"{\n"
-"      vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
-"      //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
-"      vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
-"      //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
-"      // slight water animation via 2 layer scrolling (todo: tweak)\n"
-"      #ifdef USENORMALMAPSCROLLBLEND\n"
-"              vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
-"              normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
-"              vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
-"      #else\n"
-"              vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
-"      #endif\n"
-"      // FIXME temporary hack to detect the case that the reflection\n"
-"      // gets blackened at edges due to leaving the area that contains actual\n"
-"      // content.\n"
-"      // Remove this 'ack once we have a better way to stop this thing from\n"
-"      // 'appening.\n"
-"      float f  = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
-"      f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
-"      f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
-"      f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
-"      ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
-"      f  = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
-"      f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
-"      f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
-"      f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
-"      ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
-"      float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
-"      gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
-"}\n"
-"#endif\n"
-"#else // !MODE_WATER\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"// common definitions between vertex shader and fragment shader:\n"
-"\n"
-"varying vec2 TexCoord;\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"varying vec2 TexCoord2;\n"
-"#endif\n"
-"#ifdef USELIGHTMAP\n"
-"varying vec2 TexCoordLightmap;\n"
-"#endif\n"
-"\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"varying vec3 CubeVector;\n"
-"#endif\n"
-"\n"
-"#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
-"varying vec3 LightVector;\n"
-"#endif\n"
-"\n"
-"#ifdef USEEYEVECTOR\n"
-"varying vec3 EyeVector;\n"
-"#endif\n"
-"#ifdef USEFOG\n"
-"varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
-"#endif\n"
-"\n"
-"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
-"varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
-"varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
-"varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
-"#endif\n"
-"\n"
-"#ifdef USEREFLECTION\n"
-"varying vec4 ModelViewProjectionPosition;\n"
-"#endif\n"
-"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
-"uniform vec3 LightPosition;\n"
-"varying vec4 ModelViewPosition;\n"
-"#endif\n"
-"\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"uniform vec3 LightPosition;\n"
-"#endif\n"
-"uniform vec3 EyePosition;\n"
-"#ifdef MODE_LIGHTDIRECTION\n"
-"uniform vec3 LightDir;\n"
-"#endif\n"
-"uniform vec4 FogPlane;\n"
-"\n"
-"#ifdef USESHADOWMAPORTHO\n"
-"varying vec3 ShadowMapTC;\n"
-"#endif\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
-"\n"
-"// fragment shader specific:\n"
-"#ifdef FRAGMENT_SHADER\n"
-"\n"
-"uniform sampler2D Texture_Normal;\n"
-"uniform sampler2D Texture_Color;\n"
-"uniform sampler2D Texture_Gloss;\n"
-"#ifdef USEGLOW\n"
-"uniform sampler2D Texture_Glow;\n"
-"#endif\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"uniform sampler2D Texture_SecondaryNormal;\n"
-"uniform sampler2D Texture_SecondaryColor;\n"
-"uniform sampler2D Texture_SecondaryGloss;\n"
-"#ifdef USEGLOW\n"
-"uniform sampler2D Texture_SecondaryGlow;\n"
-"#endif\n"
-"#endif\n"
-"#ifdef USECOLORMAPPING\n"
-"uniform sampler2D Texture_Pants;\n"
-"uniform sampler2D Texture_Shirt;\n"
-"#endif\n"
-"#ifdef USEFOG\n"
-"#ifdef USEFOGHEIGHTTEXTURE\n"
-"uniform sampler2D Texture_FogHeightTexture;\n"
-"#endif\n"
-"uniform sampler2D Texture_FogMask;\n"
-"#endif\n"
-"#ifdef USELIGHTMAP\n"
-"uniform sampler2D Texture_Lightmap;\n"
-"#endif\n"
-"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
-"uniform sampler2D Texture_Deluxemap;\n"
-"#endif\n"
-"#ifdef USEREFLECTION\n"
-"uniform sampler2D Texture_Reflection;\n"
-"#endif\n"
-"\n"
-"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
-"uniform sampler2D Texture_ScreenDepth;\n"
-"uniform sampler2D Texture_ScreenNormalMap;\n"
-"#endif\n"
-"#ifdef USEDEFERREDLIGHTMAP\n"
-"uniform sampler2D Texture_ScreenDiffuse;\n"
-"uniform sampler2D Texture_ScreenSpecular;\n"
-"#endif\n"
-"\n"
-"uniform myhalf3 Color_Pants;\n"
-"uniform myhalf3 Color_Shirt;\n"
-"uniform myhalf3 FogColor;\n"
-"\n"
-"#ifdef USEFOG\n"
-"uniform float FogRangeRecip;\n"
-"uniform float FogPlaneViewDist;\n"
-"uniform float FogHeightFade;\n"
-"vec3 FogVertex(vec3 surfacecolor)\n"
-"{\n"
-"      vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
-"      float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
-"      float fogfrac;\n"
-"#ifdef USEFOGHEIGHTTEXTURE\n"
-"      vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
-"      fogfrac = fogheightpixel.a;\n"
-"      return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
-"#else\n"
-"# ifdef USEFOGOUTSIDE\n"
-"      fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
-"# else\n"
-"      fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
-"# endif\n"
-"      return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
-"#endif\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef USEOFFSETMAPPING\n"
-"uniform float OffsetMapping_Scale;\n"
-"vec2 OffsetMapping(vec2 TexCoord)\n"
-"{\n"
-"#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
-"      // 14 sample relief mapping: linear search and then binary search\n"
-"      // this basically steps forward a small amount repeatedly until it finds\n"
-"      // itself inside solid, then jitters forward and back using decreasing\n"
-"      // amounts to find the impact\n"
-"      //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
-"      //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
-"      vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
-"      vec3 RT = vec3(TexCoord, 1);\n"
-"      OffsetVector *= 0.1;\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
-"      RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
-"      RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
-"      RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
-"      RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
-"      return RT.xy;\n"
-"#else\n"
-"      // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
-"      // this basically moves forward the full distance, and then backs up based\n"
-"      // on height of samples\n"
-"      //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
-"      //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
-"      vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
-"      TexCoord += OffsetVector;\n"
-"      OffsetVector *= 0.5;\n"
-"      TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
-"      TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
-"      return TexCoord;\n"
-"#endif\n"
-"}\n"
-"#endif // USEOFFSETMAPPING\n"
-"\n"
-"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
-"uniform sampler2D Texture_Attenuation;\n"
-"uniform samplerCube Texture_Cube;\n"
-"#endif\n"
-"\n"
-"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
-"\n"
-"#ifdef USESHADOWMAP2D\n"
-"# ifdef USESHADOWSAMPLER\n"
-"uniform sampler2DShadow Texture_ShadowMap2D;\n"
-"# else\n"
-"uniform sampler2D Texture_ShadowMap2D;\n"
-"# endif\n"
-"#endif\n"
-"\n"
-"#ifdef USESHADOWMAPVSDCT\n"
-"uniform samplerCube Texture_CubeProjection;\n"
-"#endif\n"
-"\n"
-"#if defined(USESHADOWMAP2D)\n"
-"uniform vec2 ShadowMap_TextureScale;\n"
-"uniform vec4 ShadowMap_Parameters;\n"
-"#endif\n"
-"\n"
-"#if defined(USESHADOWMAP2D)\n"
-"# ifdef USESHADOWMAPORTHO\n"
-"#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
-"# else\n"
-"#  ifdef USESHADOWMAPVSDCT\n"
-"vec3 GetShadowMapTC2D(vec3 dir)\n"
-"{\n"
-"      vec3 adir = abs(dir);\n"
-"      vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
-"      vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
-"      return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
-"}\n"
-"#  else\n"
-"vec3 GetShadowMapTC2D(vec3 dir)\n"
-"{\n"
-"      vec3 adir = abs(dir);\n"
-"      float ma = adir.z;\n"
-"      vec4 proj = vec4(dir, 2.5);\n"
-"      if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
-"      if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
-"      vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
-"      return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
-"}\n"
-"#  endif\n"
-"# endif\n"
-"#endif // defined(USESHADOWMAP2D)\n"
-"\n"
-"# ifdef USESHADOWMAP2D\n"
-"float ShadowMapCompare(vec3 dir)\n"
-"{\n"
-"      vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
-"      float f;\n"
-"\n"
-"#  ifdef USESHADOWSAMPLER\n"
-"#    ifdef USESHADOWMAPPCF\n"
-"#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
-"      vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
-"      f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
-"#    else\n"
-"      f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
-"#    endif\n"
-"#  else\n"
-"#    ifdef USESHADOWMAPPCF\n"
-"#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
-"#      ifdef GL_ARB_texture_gather\n"
-"#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
-"#      else\n"
-"#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
-"#      endif\n"
-"      vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
-"#      if USESHADOWMAPPCF > 1\n"
-"   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
-"   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
-"   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
-"   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
-"   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
-"   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
-"   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
-"   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
-"   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
-"      vec4 locols = vec4(group1.ab, group3.ab);\n"
-"      vec4 hicols = vec4(group7.rg, group9.rg);\n"
-"      locols.yz += group2.ab;\n"
-"      hicols.yz += group8.rg;\n"
-"      vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
-"                              vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
-"                              mix(locols, hicols, offset.y);\n"
-"      vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
-"      cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
-"      f = dot(cols, vec4(1.0/25.0));\n"
-"#      else\n"
-"      vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
-"      vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
-"      vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
-"      vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
-"      vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
-"                              mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
-"      f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
-"#      endif\n"
-"#     else\n"
-"#      ifdef GL_EXT_gpu_shader4\n"
-"#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
-"#      else\n"
-"#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
-"#      endif\n"
-"#      if USESHADOWMAPPCF > 1\n"
-"      vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
-"      center *= ShadowMap_TextureScale;\n"
-"      vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
-"      vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
-"      vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
-"      vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
-"      vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
-"      f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
-"#      else\n"
-"      vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
-"      vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
-"      vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
-"      vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
-"      vec3 cols = row2 + mix(row1, row3, offset.y);\n"
-"      f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
-"#      endif\n"
-"#     endif\n"
-"#    else\n"
-"      f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
-"#    endif\n"
-"#  endif\n"
-"#  ifdef USESHADOWMAPORTHO\n"
-"      return mix(ShadowMap_Parameters.w, 1.0, f);\n"
-"#  else\n"
-"      return f;\n"
-"#  endif\n"
-"}\n"
-"# endif\n"
-"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
-"#endif // FRAGMENT_SHADER\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_DEFERREDGEOMETRY\n"
-"#ifdef VERTEX_SHADER\n"
-"uniform mat4 TexMatrix;\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"uniform mat4 BackgroundTexMatrix;\n"
-"#endif\n"
-"uniform mat4 ModelViewMatrix;\n"
-"void main(void)\n"
-"{\n"
-"      TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"      gl_FrontColor = gl_Color;\n"
-"      TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
-"#endif\n"
-"\n"
-"      // transform unnormalized eye direction into tangent space\n"
-"#ifdef USEOFFSETMAPPING\n"
-"      vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
-"      EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
-"      EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
-"      EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
-"#endif\n"
-"\n"
-"      VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
-"      VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
-"      VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
-"      gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
-"}\n"
-"#endif // VERTEX_SHADER\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"void main(void)\n"
-"{\n"
-"#ifdef USEOFFSETMAPPING\n"
-"      // apply offsetmapping\n"
-"      vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
-"#define TexCoord TexCoordOffset\n"
-"#endif\n"
-"\n"
-"#ifdef USEALPHAKILL\n"
-"      if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
-"              discard;\n"
-"#endif\n"
-"\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"      float alpha = texture2D(Texture_Color, TexCoord).a;\n"
-"      float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
-"      //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
-"      //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
-"#endif\n"
-"\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"      vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
-"      float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
-"#else\n"
-"      vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
-"      float a = texture2D(Texture_Gloss, TexCoord).a;\n"
-"#endif\n"
-"\n"
-"      gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
-"}\n"
-"#endif // FRAGMENT_SHADER\n"
-"#else // !MODE_DEFERREDGEOMETRY\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
-"#ifdef VERTEX_SHADER\n"
-"uniform mat4 ModelViewMatrix;\n"
-"void main(void)\n"
-"{\n"
-"      ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
-"      gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
-"}\n"
-"#endif // VERTEX_SHADER\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"uniform mat4 ViewToLight;\n"
-"// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
-"uniform vec2 ScreenToDepth;\n"
-"uniform myhalf3 DeferredColor_Ambient;\n"
-"uniform myhalf3 DeferredColor_Diffuse;\n"
-"#ifdef USESPECULAR\n"
-"uniform myhalf3 DeferredColor_Specular;\n"
-"uniform myhalf SpecularPower;\n"
-"#endif\n"
-"uniform myhalf2 PixelToScreenTexCoord;\n"
-"void main(void)\n"
-"{\n"
-"      // calculate viewspace pixel position\n"
-"      vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
-"      vec3 position;\n"
-"      position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
-"      position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
-"      // decode viewspace pixel normal\n"
-"      myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
-"      myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
-"      // surfacenormal = pixel normal in viewspace\n"
-"      // LightVector = pixel to light in viewspace\n"
-"      // CubeVector = position in lightspace\n"
-"      // eyevector = pixel to view in viewspace\n"
-"      vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
-"      myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
-"#ifdef USEDIFFUSE\n"
-"      // calculate diffuse shading\n"
-"      myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
-"      myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
-"#endif\n"
-"#ifdef USESPECULAR\n"
-"      // calculate directional shading\n"
-"      vec3 eyevector = position * -1.0;\n"
-"#  ifdef USEEXACTSPECULARMATH\n"
-"      myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
-"#  else\n"
-"      myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
-"      myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
-"#  endif\n"
-"#endif\n"
-"\n"
-"#if defined(USESHADOWMAP2D)\n"
-"      fade *= ShadowMapCompare(CubeVector);\n"
-"#endif\n"
-"\n"
-"#ifdef USEDIFFUSE\n"
-"      gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
-"#else\n"
-"      gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
-"#endif\n"
-"#ifdef USESPECULAR\n"
-"      gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
-"#else\n"
-"      gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
-"#endif\n"
-"\n"
-"# ifdef USECUBEFILTER\n"
-"      vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
-"      gl_FragData[0].rgb *= cubecolor;\n"
-"      gl_FragData[1].rgb *= cubecolor;\n"
-"# endif\n"
-"}\n"
-"#endif // FRAGMENT_SHADER\n"
-"#else // !MODE_DEFERREDLIGHTSOURCE\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef VERTEX_SHADER\n"
-"uniform mat4 TexMatrix;\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"uniform mat4 BackgroundTexMatrix;\n"
-"#endif\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"uniform mat4 ModelToLight;\n"
-"#endif\n"
-"#ifdef USESHADOWMAPORTHO\n"
-"uniform mat4 ShadowMapMatrix;\n"
-"#endif\n"
-"void main(void)\n"
-"{\n"
-"#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
-"      gl_FrontColor = gl_Color;\n"
-"#endif\n"
-"      // copy the surface texcoord\n"
-"      TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"      TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
-"#endif\n"
-"#ifdef USELIGHTMAP\n"
-"      TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
-"#endif\n"
-"\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"      // transform vertex position into light attenuation/cubemap space\n"
-"      // (-1 to +1 across the light box)\n"
-"      CubeVector = vec3(ModelToLight * gl_Vertex);\n"
-"\n"
-"# ifdef USEDIFFUSE\n"
-"      // transform unnormalized light direction into tangent space\n"
-"      // (we use unnormalized to ensure that it interpolates correctly and then\n"
-"      //  normalize it per pixel)\n"
-"      vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
-"      LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
-"      LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
-"      LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
-"# endif\n"
-"#endif\n"
-"\n"
-"#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
-"      LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
-"      LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
-"      LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
-"#endif\n"
-"\n"
-"      // transform unnormalized eye direction into tangent space\n"
-"#ifdef USEEYEVECTOR\n"
-"      vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
-"      EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
-"      EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
-"      EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
-"#endif\n"
-"\n"
-"#ifdef USEFOG\n"
-"      EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
-"      EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
-"#endif\n"
-"\n"
-"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
-"      VectorS = gl_MultiTexCoord1.xyz;\n"
-"      VectorT = gl_MultiTexCoord2.xyz;\n"
-"      VectorR = gl_MultiTexCoord3.xyz;\n"
-"#endif\n"
-"\n"
-"      // transform vertex to camera space, using ftransform to match non-VS rendering\n"
-"      gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
-"\n"
-"#ifdef USESHADOWMAPORTHO\n"
-"      ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
-"#endif\n"
-"\n"
-"#ifdef USEREFLECTION\n"
-"      ModelViewProjectionPosition = gl_Position;\n"
-"#endif\n"
-"}\n"
-"#endif // VERTEX_SHADER\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"#ifdef USEDEFERREDLIGHTMAP\n"
-"uniform myhalf2 PixelToScreenTexCoord;\n"
-"uniform myhalf3 DeferredMod_Diffuse;\n"
-"uniform myhalf3 DeferredMod_Specular;\n"
-"#endif\n"
-"uniform myhalf3 Color_Ambient;\n"
-"uniform myhalf3 Color_Diffuse;\n"
-"uniform myhalf3 Color_Specular;\n"
-"uniform myhalf SpecularPower;\n"
-"#ifdef USEGLOW\n"
-"uniform myhalf3 Color_Glow;\n"
-"#endif\n"
-"uniform myhalf Alpha;\n"
-"#ifdef USEREFLECTION\n"
-"uniform vec4 DistortScaleRefractReflect;\n"
-"uniform vec4 ScreenScaleRefractReflect;\n"
-"uniform vec4 ScreenCenterRefractReflect;\n"
-"uniform myhalf4 ReflectColor;\n"
-"#endif\n"
-"#ifdef USEREFLECTCUBE\n"
-"uniform mat4 ModelToReflectCube;\n"
-"uniform sampler2D Texture_ReflectMask;\n"
-"uniform samplerCube Texture_ReflectCube;\n"
-"#endif\n"
-"#ifdef MODE_LIGHTDIRECTION\n"
-"uniform myhalf3 LightColor;\n"
-"#endif\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"uniform myhalf3 LightColor;\n"
-"#endif\n"
-"void main(void)\n"
-"{\n"
-"#ifdef USEOFFSETMAPPING\n"
-"      // apply offsetmapping\n"
-"      vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
-"#define TexCoord TexCoordOffset\n"
-"#endif\n"
-"\n"
-"      // combine the diffuse textures (base, pants, shirt)\n"
-"      myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
-"#ifdef USEALPHAKILL\n"
-"      if (color.a < 0.5)\n"
-"              discard;\n"
-"#endif\n"
-"      color.a *= Alpha;\n"
-"#ifdef USECOLORMAPPING\n"
-"      color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
-"#endif\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"      myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
-"      //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
-"      //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
-"      color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
-"      color.a = 1.0;\n"
-"      //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
-"#endif\n"
-"\n"
-"      // get the surface normal\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"      myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
-"#else\n"
-"      myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
-"#endif\n"
-"\n"
-"      // get the material colors\n"
-"      myhalf3 diffusetex = color.rgb;\n"
-"#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
-"# ifdef USEVERTEXTEXTUREBLEND\n"
-"      myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
-"# else\n"
-"      myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
-"# endif\n"
-"#endif\n"
-"\n"
-"#ifdef USEREFLECTCUBE\n"
-"      vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
-"      vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
-"      vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
-"      diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
-"#endif\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"      // light source\n"
-"#ifdef USEDIFFUSE\n"
-"      myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
-"      myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
-"      color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
-"#ifdef USESPECULAR\n"
-"#ifdef USEEXACTSPECULARMATH\n"
-"      myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
-"#else\n"
-"      myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
-"      myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
-"#endif\n"
-"      color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
-"#endif\n"
-"#else\n"
-"      color.rgb = diffusetex * Color_Ambient;\n"
-"#endif\n"
-"      color.rgb *= LightColor;\n"
-"      color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
-"#if defined(USESHADOWMAP2D)\n"
-"      color.rgb *= ShadowMapCompare(CubeVector);\n"
-"#endif\n"
-"# ifdef USECUBEFILTER\n"
-"      color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
-"# endif\n"
-"#endif // MODE_LIGHTSOURCE\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_LIGHTDIRECTION\n"
-"#define SHADING\n"
-"#ifdef USEDIFFUSE\n"
-"      myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
-"#endif\n"
-"#define lightcolor LightColor\n"
-"#endif // MODE_LIGHTDIRECTION\n"
-"#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
-"#define SHADING\n"
-"      // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
-"      myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
-"      myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
-"      // convert modelspace light vector to tangentspace\n"
-"      myhalf3 lightnormal;\n"
-"      lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
-"      lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
-"      lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
-"      lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
-"      // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
-"      // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
-"      // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
-"      // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
-"      // to map the luxels to coordinates on the draw surfaces), which also causes\n"
-"      // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
-"      // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
-"      // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
-"      // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
-"      lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
-"#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
-"#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
-"#define SHADING\n"
-"      // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
-"      myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
-"      myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
-"#endif\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_FAKELIGHT\n"
-"#define SHADING\n"
-"myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
-"myhalf3 lightcolor = myhalf3(1.0);\n"
-"#endif // MODE_FAKELIGHT\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_LIGHTMAP\n"
-"      color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
-"#endif // MODE_LIGHTMAP\n"
-"#ifdef MODE_VERTEXCOLOR\n"
-"      color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
-"#endif // MODE_VERTEXCOLOR\n"
-"#ifdef MODE_FLATCOLOR\n"
-"      color.rgb = diffusetex * Color_Ambient;\n"
-"#endif // MODE_FLATCOLOR\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef SHADING\n"
-"# ifdef USEDIFFUSE\n"
-"      myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
-"#  ifdef USESPECULAR\n"
-"#   ifdef USEEXACTSPECULARMATH\n"
-"      myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
-"#   else\n"
-"      myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
-"      myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
-"#   endif\n"
-"      color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
-"#  else\n"
-"      color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
-"#  endif\n"
-"# else\n"
-"      color.rgb = diffusetex * Color_Ambient;\n"
-"# endif\n"
-"#endif\n"
-"\n"
-"#ifdef USESHADOWMAPORTHO\n"
-"      color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
-"#endif\n"
-"\n"
-"#ifdef USEDEFERREDLIGHTMAP\n"
-"      vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
-"      color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
-"      color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
-"#endif\n"
-"\n"
-"#ifdef USEGLOW\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"      color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
-"#else\n"
-"      color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
-"#endif\n"
-"#endif\n"
-"\n"
-"#ifdef USEFOG\n"
-"      color.rgb = FogVertex(color.rgb);\n"
-"#endif\n"
-"\n"
-"      // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
-"#ifdef USEREFLECTION\n"
-"      vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
-"      //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
-"      vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
-"      vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
-"      // FIXME temporary hack to detect the case that the reflection\n"
-"      // gets blackened at edges due to leaving the area that contains actual\n"
-"      // content.\n"
-"      // Remove this 'ack once we have a better way to stop this thing from\n"
-"      // 'appening.\n"
-"      float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
-"      ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
-"      color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
-"#endif\n"
-"\n"
-"      gl_FragColor = vec4(color);\n"
-"}\n"
-"#endif // FRAGMENT_SHADER\n"
-"\n"
-"#endif // !MODE_DEFERREDLIGHTSOURCE\n"
-"#endif // !MODE_DEFERREDGEOMETRY\n"
-"#endif // !MODE_WATER\n"
-"#endif // !MODE_REFRACTION\n"
-"#endif // !MODE_BLOOMBLUR\n"
-"#endif // !MODE_GENERIC\n"
-"#endif // !MODE_POSTPROCESS\n"
-"#endif // !MODE_SHOWDEPTH\n"
-"#endif // !MODE_DEPTH_OR_SHADOW\n"
+#include "shader_glsl.h"
 ;
 
-/*
-=========================================================================================================================================================
-
-
-
-=========================================================================================================================================================
-
-
-
-=========================================================================================================================================================
-
-
-
-=========================================================================================================================================================
-
-
-
-=========================================================================================================================================================
-
-
-
-=========================================================================================================================================================
-
-
-
-=========================================================================================================================================================
-*/
-
-const char *builtincgshaderstring =
-"// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
-"// written by Forest 'LordHavoc' Hale\n"
-"// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
-"\n"
-"// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
-"#if defined(USEREFLECTION)\n"
-"#undef USESHADOWMAPORTHO\n"
-"#endif\n"
-"\n"
-"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
-"# define USEFOG\n"
-"#endif\n"
-"#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
-"#define USELIGHTMAP\n"
-"#endif\n"
-"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
-"#define USEEYEVECTOR\n"
-"#endif\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"#ifdef HLSL\n"
-"//#undef USESHADOWMAPPCF\n"
-"//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
-"#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
-"#else\n"
-"#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
-"#endif\n"
-"#endif\n"
-"\n"
-"#ifdef MODE_DEPTH_OR_SHADOW\n"
-"#ifdef VERTEX_SHADER\n"
-"void main\n"
-"(\n"
-"float4 gl_Vertex : POSITION,\n"
-"uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
-"out float4 gl_Position : POSITION,\n"
-"out float Depth : TEXCOORD0\n"
-")\n"
-"{\n"
-"      gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
-"      Depth = gl_Position.z;\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"void main\n"
-"(\n"
-"float Depth : TEXCOORD0,\n"
-"out float4 gl_FragColor : COLOR\n"
-")\n"
-"{\n"
-"//    float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
-"      float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
-"      temp.yz -= floor(temp.yz);\n"
-"      gl_FragColor = temp;\n"
-"//    gl_FragColor = float4(Depth,0,0,0);\n"
-"}\n"
-"#endif\n"
-"#else // !MODE_DEPTH_ORSHADOW\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_SHOWDEPTH\n"
-"#ifdef VERTEX_SHADER\n"
-"void main\n"
-"(\n"
-"float4 gl_Vertex : POSITION,\n"
-"uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
-"out float4 gl_Position : POSITION,\n"
-"out float4 gl_FrontColor : COLOR0\n"
-")\n"
-"{\n"
-"      gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
-"      gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"void main\n"
-"(\n"
-"float4 gl_FrontColor : COLOR0,\n"
-"out float4 gl_FragColor : COLOR\n"
-")\n"
-"{\n"
-"      gl_FragColor = gl_FrontColor;\n"
-"}\n"
-"#endif\n"
-"#else // !MODE_SHOWDEPTH\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_POSTPROCESS\n"
-"\n"
-"#ifdef VERTEX_SHADER\n"
-"void main\n"
-"(\n"
-"float4 gl_Vertex : POSITION,\n"
-"uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
-"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
-"float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
-"out float4 gl_Position : POSITION,\n"
-"out float2 TexCoord1 : TEXCOORD0,\n"
-"out float2 TexCoord2 : TEXCOORD1\n"
-")\n"
-"{\n"
-"      gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
-"      TexCoord1 = gl_MultiTexCoord0.xy;\n"
-"#ifdef USEBLOOM\n"
-"      TexCoord2 = gl_MultiTexCoord4.xy;\n"
-"#endif\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"void main\n"
-"(\n"
-"float2 TexCoord1 : TEXCOORD0,\n"
-"float2 TexCoord2 : TEXCOORD1,\n"
-"uniform sampler Texture_First : register(s0),\n"
-"#ifdef USEBLOOM\n"
-"uniform sampler Texture_Second : register(s1),\n"
-"#endif\n"
-"#ifdef USEGAMMARAMPS\n"
-"uniform sampler Texture_GammaRamps : register(s2),\n"
-"#endif\n"
-"#ifdef USESATURATION\n"
-"uniform float Saturation : register(c30),\n"
-"#endif\n"
-"#ifdef USEVIEWTINT\n"
-"uniform float4 ViewTintColor : register(c41),\n"
-"#endif\n"
-"uniform float4 UserVec1 : register(c37),\n"
-"uniform float4 UserVec2 : register(c38),\n"
-"uniform float4 UserVec3 : register(c39),\n"
-"uniform float4 UserVec4 : register(c40),\n"
-"uniform float ClientTime : register(c2),\n"
-"uniform float2 PixelSize : register(c25),\n"
-"uniform float4 BloomColorSubtract : register(c43),\n"
-"out float4 gl_FragColor : COLOR\n"
-")\n"
-"{\n"
-"      gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
-"#ifdef USEBLOOM\n"
-"      gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
-"#endif\n"
-"#ifdef USEVIEWTINT\n"
-"      gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
-"#endif\n"
-"\n"
-"#ifdef USEPOSTPROCESSING\n"
-"// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
-"// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
-"      float sobel = 1.0;\n"
-"      // float2 ts = textureSize(Texture_First, 0);\n"
-"      // float2 px = float2(1/ts.x, 1/ts.y);\n"
-"      float2 px = PixelSize;\n"
-"      float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
-"      float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
-"      float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
-"      float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
-"      float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
-"      float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
-"      float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
-"      float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
-"      float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
-"      float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
-"      float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
-"      float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
-"      float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
-"      float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
-"      float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
-"      float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
-"      float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
-"      float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
-"      float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
-"      float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
-"      float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
-"      float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
-"      float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
-"      float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
-"      sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
-"      gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
-"      gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
-"      gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
-"      gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
-"      gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
-"      gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
-"      gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
-"#endif\n"
-"\n"
-"#ifdef USESATURATION\n"
-"      //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
-"      float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
-"      // 'vampire sight' effect, wheres red is compensated\n"
-"      #ifdef SATURATION_REDCOMPENSATE\n"
-"              float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
-"              gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
-"              gl_FragColor.r += r;\n"
-"      #else\n"
-"              // normal desaturation\n"
-"              //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
-"              gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
-"      #endif\n"
-"#endif\n"
-"\n"
-"#ifdef USEGAMMARAMPS\n"
-"      gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
-"      gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
-"      gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
-"#endif\n"
-"}\n"
-"#endif\n"
-"#else // !MODE_POSTPROCESS\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_GENERIC\n"
-"#ifdef VERTEX_SHADER\n"
-"void main\n"
-"(\n"
-"float4 gl_Vertex : POSITION,\n"
-"uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
-"float4 gl_Color : COLOR0,\n"
-"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
-"float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
-"out float4 gl_Position : POSITION,\n"
-"#ifdef USEDIFFUSE\n"
-"out float2 TexCoord1 : TEXCOORD0,\n"
-"#endif\n"
-"#ifdef USESPECULAR\n"
-"out float2 TexCoord2 : TEXCOORD1,\n"
-"#endif\n"
-"out float4 gl_FrontColor : COLOR\n"
-")\n"
-"{\n"
-"#ifdef HLSL\n"
-"      gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
-"#else\n"
-"      gl_FrontColor = gl_Color; // Cg is forward\n"
-"#endif\n"
-"#ifdef USEDIFFUSE\n"
-"      TexCoord1 = gl_MultiTexCoord0.xy;\n"
-"#endif\n"
-"#ifdef USESPECULAR\n"
-"      TexCoord2 = gl_MultiTexCoord1.xy;\n"
-"#endif\n"
-"      gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"\n"
-"void main\n"
-"(\n"
-"float4 gl_FrontColor : COLOR0,\n"
-"float2 TexCoord1 : TEXCOORD0,\n"
-"float2 TexCoord2 : TEXCOORD1,\n"
-"#ifdef USEDIFFUSE\n"
-"uniform sampler Texture_First : register(s0),\n"
-"#endif\n"
-"#ifdef USESPECULAR\n"
-"uniform sampler Texture_Second : register(s1),\n"
-"#endif\n"
-"out float4 gl_FragColor : COLOR\n"
-")\n"
-"{\n"
-"#ifdef USEVIEWTINT\n"
-"      gl_FragColor = gl_FrontColor;\n"
-"#else\n"
-"      gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
-"#endif\n"
-"#ifdef USEDIFFUSE\n"
-"      gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
-"#endif\n"
-"\n"
-"#ifdef USESPECULAR\n"
-"      float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
-"# ifdef USECOLORMAPPING\n"
-"      gl_FragColor *= tex2;\n"
-"# endif\n"
-"# ifdef USEGLOW\n"
-"      gl_FragColor += tex2;\n"
-"# endif\n"
-"# ifdef USEVERTEXTEXTUREBLEND\n"
-"      gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
-"# endif\n"
-"#endif\n"
-"}\n"
-"#endif\n"
-"#else // !MODE_GENERIC\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_BLOOMBLUR\n"
-"#ifdef VERTEX_SHADER\n"
-"void main\n"
-"(\n"
-"float4 gl_Vertex : POSITION,\n"
-"uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
-"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
-"out float4 gl_Position : POSITION,\n"
-"out float2 TexCoord : TEXCOORD0\n"
-")\n"
-"{\n"
-"      TexCoord = gl_MultiTexCoord0.xy;\n"
-"      gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"\n"
-"void main\n"
-"(\n"
-"float2 TexCoord : TEXCOORD0,\n"
-"uniform sampler Texture_First : register(s0),\n"
-"uniform float4 BloomBlur_Parameters : register(c1),\n"
-"out float4 gl_FragColor : COLOR\n"
-")\n"
-"{\n"
-"      int i;\n"
-"      float2 tc = TexCoord;\n"
-"      float3 color = tex2D(Texture_First, tc).rgb;\n"
-"      tc += BloomBlur_Parameters.xy;\n"
-"      for (i = 1;i < SAMPLES;i++)\n"
-"      {\n"
-"              color += tex2D(Texture_First, tc).rgb;\n"
-"              tc += BloomBlur_Parameters.xy;\n"
-"      }\n"
-"      gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
-"}\n"
-"#endif\n"
-"#else // !MODE_BLOOMBLUR\n"
-"#ifdef MODE_REFRACTION\n"
-"#ifdef VERTEX_SHADER\n"
-"void main\n"
-"(\n"
-"float4 gl_Vertex : POSITION,\n"
-"uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
-"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
-"uniform float4x4 TexMatrix : register(c0),\n"
-"uniform float3 EyePosition : register(c24),\n"
-"out float4 gl_Position : POSITION,\n"
-"out float2 TexCoord : TEXCOORD0,\n"
-"out float3 EyeVector : TEXCOORD1,\n"
-"out float4 ModelViewProjectionPosition : TEXCOORD2\n"
-")\n"
-"{\n"
-"      TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
-"      gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
-"      ModelViewProjectionPosition = gl_Position;\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"void main\n"
-"(\n"
-"float2 TexCoord : TEXCOORD0,\n"
-"float3 EyeVector : TEXCOORD1,\n"
-"float4 ModelViewProjectionPosition : TEXCOORD2,\n"
-"uniform sampler Texture_Normal : register(s0),\n"
-"uniform sampler Texture_Refraction : register(s3),\n"
-"uniform sampler Texture_Reflection : register(s7),\n"
-"uniform float4 DistortScaleRefractReflect : register(c14),\n"
-"uniform float4 ScreenScaleRefractReflect : register(c32),\n"
-"uniform float4 ScreenCenterRefractReflect : register(c31),\n"
-"uniform float4 RefractColor : register(c29),\n"
-"out float4 gl_FragColor : COLOR\n"
-")\n"
-"{\n"
-"      float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
-"      //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
-"      float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
-"      float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
-"      // FIXME temporary hack to detect the case that the reflection\n"
-"      // gets blackened at edges due to leaving the area that contains actual\n"
-"      // content.\n"
-"      // Remove this 'ack once we have a better way to stop this thing from\n"
-"      // 'appening.\n"
-"      float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
-"      ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
-"      gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
-"}\n"
-"#endif\n"
-"#else // !MODE_REFRACTION\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_WATER\n"
-"#ifdef VERTEX_SHADER\n"
-"\n"
-"void main\n"
-"(\n"
-"float4 gl_Vertex : POSITION,\n"
-"uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
-"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
-"float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
-"float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
-"float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
-"uniform float4x4 TexMatrix : register(c0),\n"
-"uniform float3 EyePosition : register(c24),\n"
-"out float4 gl_Position : POSITION,\n"
-"out float2 TexCoord : TEXCOORD0,\n"
-"out float3 EyeVector : TEXCOORD1,\n"
-"out float4 ModelViewProjectionPosition : TEXCOORD2\n"
-")\n"
-"{\n"
-"      TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
-"      float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
-"      EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
-"      EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
-"      EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
-"      gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
-"      ModelViewProjectionPosition = gl_Position;\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"void main\n"
-"(\n"
-"float2 TexCoord : TEXCOORD0,\n"
-"float3 EyeVector : TEXCOORD1,\n"
-"float4 ModelViewProjectionPosition : TEXCOORD2,\n"
-"uniform sampler Texture_Normal : register(s0),\n"
-"uniform sampler Texture_Refraction : register(s3),\n"
-"uniform sampler Texture_Reflection : register(s7),\n"
-"uniform float4 DistortScaleRefractReflect : register(c14),\n"
-"uniform float4 ScreenScaleRefractReflect : register(c32),\n"
-"uniform float4 ScreenCenterRefractReflect : register(c31),\n"
-"uniform float4 RefractColor : register(c29),\n"
-"uniform float4 ReflectColor : register(c26),\n"
-"uniform float ReflectFactor : register(c27),\n"
-"uniform float ReflectOffset : register(c28),\n"
-"out float4 gl_FragColor : COLOR\n"
-")\n"
-"{\n"
-"      float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
-"      //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
-"      float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
-"      //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
-"      float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
-"      // FIXME temporary hack to detect the case that the reflection\n"
-"      // gets blackened at edges due to leaving the area that contains actual\n"
-"      // content.\n"
-"      // Remove this 'ack once we have a better way to stop this thing from\n"
-"      // 'appening.\n"
-"      float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
-"      ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
-"      f  = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
-"      f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
-"      f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
-"      f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
-"      ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
-"      float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
-"      gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
-"}\n"
-"#endif\n"
-"#else // !MODE_WATER\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
-"\n"
-"// fragment shader specific:\n"
-"#ifdef FRAGMENT_SHADER\n"
-"\n"
-"#ifdef USEFOG\n"
-"float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
-"{\n"
-"      float fogfrac;\n"
-"#ifdef USEFOGHEIGHTTEXTURE\n"
-"      float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
-"      fogfrac = fogheightpixel.a;\n"
-"      return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
-"#else\n"
-"# ifdef USEFOGOUTSIDE\n"
-"      fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
-"# else\n"
-"      fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
-"# endif\n"
-"      return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
-"#endif\n"
-"}\n"
-"#endif\n"
-"\n"
-"#ifdef USEOFFSETMAPPING\n"
-"float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
-"{\n"
-"#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
-"      // 14 sample relief mapping: linear search and then binary search\n"
-"      // this basically steps forward a small amount repeatedly until it finds\n"
-"      // itself inside solid, then jitters forward and back using decreasing\n"
-"      // amounts to find the impact\n"
-"      //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
-"      //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
-"      float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
-"      float3 RT = float3(TexCoord, 1);\n"
-"      OffsetVector *= 0.1;\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
-"      RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
-"      RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
-"      RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
-"      RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
-"      RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
-"      return RT.xy;\n"
-"#else\n"
-"      // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
-"      // this basically moves forward the full distance, and then backs up based\n"
-"      // on height of samples\n"
-"      //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
-"      //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
-"      float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
-"      TexCoord += OffsetVector;\n"
-"      OffsetVector *= 0.333;\n"
-"      TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
-"      TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
-"      TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
-"      return TexCoord;\n"
-"#endif\n"
-"}\n"
-"#endif // USEOFFSETMAPPING\n"
-"\n"
-"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
-"#if defined(USESHADOWMAP2D)\n"
-"# ifdef USESHADOWMAPORTHO\n"
-"#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
-"# else\n"
-"#  ifdef USESHADOWMAPVSDCT\n"
-"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
-"{\n"
-"      float3 adir = abs(dir);\n"
-"      float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
-"      float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
-"      return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
-"}\n"
-"#  else\n"
-"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
-"{\n"
-"      float3 adir = abs(dir);\n"
-"      float ma = adir.z;\n"
-"      float4 proj = float4(dir, 2.5);\n"
-"      if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
-"      if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
-"#ifdef HLSL\n"
-"      return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
-"#else\n"
-"      float2 aparams = ShadowMap_Parameters.xy / ma;\n"
-"      return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
-"#endif\n"
-"}\n"
-"#  endif\n"
-"# endif\n"
-"#endif // defined(USESHADOWMAP2D)\n"
-"\n"
-"# ifdef USESHADOWMAP2D\n"
-"#ifdef USESHADOWMAPVSDCT\n"
-"float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
-"#else\n"
-"float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
-"#endif\n"
-"{\n"
-"#ifdef USESHADOWMAPVSDCT\n"
-"      float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
-"#else\n"
-"      float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
-"#endif\n"
-"      float f;\n"
-"\n"
-"#  ifdef USESHADOWSAMPLER\n"
-"#    ifdef USESHADOWMAPPCF\n"
-"#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
-"      float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
-"      f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
-"#    else\n"
-"      f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
-"#    endif\n"
-"#  else\n"
-"#    ifdef USESHADOWMAPPCF\n"
-"#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
-"#      ifdef GL_ARB_texture_gather\n"
-"#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
-"#      else\n"
-"#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
-"#      endif\n"
-"      float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
-"#      if USESHADOWMAPPCF > 1\n"
-"      float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
-"      float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
-"      float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
-"      float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
-"      float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
-"      float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
-"      float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
-"      float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
-"      float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
-"      float4 locols = float4(group1.ab, group3.ab);\n"
-"      float4 hicols = float4(group7.rg, group9.rg);\n"
-"      locols.yz += group2.ab;\n"
-"      hicols.yz += group8.rg;\n"
-"      float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
-"                              float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
-"                              lerp(locols, hicols, offset.y);\n"
-"      float4 cols = group5 + float4(group2.rg, group8.ab);\n"
-"      cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
-"      f = dot(cols, float4(1.0/25.0));\n"
-"#      else\n"
-"      float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
-"      float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
-"      float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
-"      float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
-"      float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
-"                              lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
-"      f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
-"#      endif\n"
-"#     else\n"
-"#      ifdef GL_EXT_gpu_shader4\n"
-"#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
-"#      else\n"
-"#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
-"#      endif\n"
-"#      if USESHADOWMAPPCF > 1\n"
-"      float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
-"      center *= ShadowMap_TextureScale;\n"
-"      float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
-"      float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
-"      float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
-"      float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
-"      float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
-"      f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
-"#      else\n"
-"      float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
-"      float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
-"      float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
-"      float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
-"      float3 cols = row2 + lerp(row1, row3, offset.y);\n"
-"      f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
-"#      endif\n"
-"#     endif\n"
-"#    else\n"
-"      f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
-"#    endif\n"
-"#  endif\n"
-"#  ifdef USESHADOWMAPORTHO\n"
-"      return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
-"#  else\n"
-"      return f;\n"
-"#  endif\n"
-"}\n"
-"# endif\n"
-"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
-"#endif // FRAGMENT_SHADER\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_DEFERREDGEOMETRY\n"
-"#ifdef VERTEX_SHADER\n"
-"void main\n"
-"(\n"
-"float4 gl_Vertex : POSITION,\n"
-"uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"float4 gl_Color : COLOR0,\n"
-"#endif\n"
-"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
-"float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
-"float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
-"float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
-"uniform float4x4 TexMatrix : register(c0),\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"uniform float4x4 BackgroundTexMatrix : register(c4),\n"
-"#endif\n"
-"uniform float4x4 ModelViewMatrix : register(c12),\n"
-"#ifdef USEOFFSETMAPPING\n"
-"uniform float3 EyePosition : register(c24),\n"
-"#endif\n"
-"out float4 gl_Position : POSITION,\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"out float4 gl_FrontColor : COLOR,\n"
-"#endif\n"
-"out float4 TexCoordBoth : TEXCOORD0,\n"
-"#ifdef USEOFFSETMAPPING\n"
-"out float3 EyeVector : TEXCOORD2,\n"
-"#endif\n"
-"out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
-"out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
-"out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
-")\n"
-"{\n"
-"      TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"#ifdef HLSL\n"
-"      gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
-"#else\n"
-"      gl_FrontColor = gl_Color; // Cg is forward\n"
-"#endif\n"
-"      TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
-"#endif\n"
-"\n"
-"      // transform unnormalized eye direction into tangent space\n"
-"#ifdef USEOFFSETMAPPING\n"
-"      float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
-"      EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
-"      EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
-"      EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
-"#endif\n"
-"\n"
-"      VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
-"      VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
-"      VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
-"      gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
-"      VectorR.w = gl_Position.z;\n"
-"}\n"
-"#endif // VERTEX_SHADER\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"void main\n"
-"(\n"
-"float4 TexCoordBoth : TEXCOORD0,\n"
-"float3 EyeVector : TEXCOORD2,\n"
-"float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
-"float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
-"float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
-"uniform sampler Texture_Normal : register(s0),\n"
-"#ifdef USEALPHAKILL\n"
-"uniform sampler Texture_Color : register(s1),\n"
-"#endif\n"
-"uniform sampler Texture_Gloss : register(s2),\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"uniform sampler Texture_SecondaryNormal : register(s4),\n"
-"uniform sampler Texture_SecondaryGloss : register(s6),\n"
-"#endif\n"
-"#ifdef USEOFFSETMAPPING\n"
-"uniform float OffsetMapping_Scale : register(c24),\n"
-"#endif\n"
-"uniform half SpecularPower : register(c36),\n"
-"#ifdef HLSL\n"
-"out float4 gl_FragData0 : COLOR0,\n"
-"out float4 gl_FragData1 : COLOR1\n"
-"#else\n"
-"out float4 gl_FragColor : COLOR\n"
-"#endif\n"
-")\n"
-"{\n"
-"      float2 TexCoord = TexCoordBoth.xy;\n"
-"#ifdef USEOFFSETMAPPING\n"
-"      // apply offsetmapping\n"
-"      float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
-"#define TexCoord TexCoordOffset\n"
-"#endif\n"
-"\n"
-"#ifdef USEALPHAKILL\n"
-"      if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
-"              discard;\n"
-"#endif\n"
-"\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"      float alpha = tex2D(Texture_Color, TexCoord).a;\n"
-"      float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
-"      //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
-"      //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
-"#endif\n"
-"\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"      float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
-"      float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
-"#else\n"
-"      float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
-"      float a = tex2D(Texture_Gloss, TexCoord).a;\n"
-"#endif\n"
-"\n"
-"#ifdef HLSL\n"
-"      gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
-"      float Depth = VectorR.w / 256.0;\n"
-"      float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
-"//    float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
-"      depthcolor.yz -= floor(depthcolor.yz);\n"
-"      gl_FragData1 = depthcolor;\n"
-"#else\n"
-"      gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
-"#endif\n"
-"}\n"
-"#endif // FRAGMENT_SHADER\n"
-"#else // !MODE_DEFERREDGEOMETRY\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
-"#ifdef VERTEX_SHADER\n"
-"void main\n"
-"(\n"
-"float4 gl_Vertex : POSITION,\n"
-"uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
-"uniform float4x4 ModelViewMatrix : register(c12),\n"
-"out float4 gl_Position : POSITION,\n"
-"out float4 ModelViewPosition : TEXCOORD0\n"
-")\n"
-"{\n"
-"      ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
-"      gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
-"}\n"
-"#endif // VERTEX_SHADER\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"void main\n"
-"(\n"
-"#ifdef HLSL\n"
-"float2 Pixel : VPOS,\n"
-"#else\n"
-"float2 Pixel : WPOS,\n"
-"#endif\n"
-"float4 ModelViewPosition : TEXCOORD0,\n"
-"uniform float4x4 ViewToLight : register(c44),\n"
-"uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
-"uniform float3 LightPosition : register(c23),\n"
-"uniform half2 PixelToScreenTexCoord : register(c42),\n"
-"uniform half3 DeferredColor_Ambient : register(c9),\n"
-"uniform half3 DeferredColor_Diffuse : register(c10),\n"
-"#ifdef USESPECULAR\n"
-"uniform half3 DeferredColor_Specular : register(c11),\n"
-"uniform half SpecularPower : register(c36),\n"
-"#endif\n"
-"uniform sampler Texture_Attenuation : register(s9),\n"
-"uniform sampler Texture_ScreenDepth : register(s13),\n"
-"uniform sampler Texture_ScreenNormalMap : register(s14),\n"
-"\n"
-"#ifdef USECUBEFILTER\n"
-"uniform samplerCUBE Texture_Cube : register(s10),\n"
-"#endif\n"
-"\n"
-"#ifdef USESHADOWMAP2D\n"
-"# ifdef USESHADOWSAMPLER\n"
-"uniform sampler Texture_ShadowMap2D : register(s15),\n"
-"# else\n"
-"uniform sampler Texture_ShadowMap2D : register(s15),\n"
-"# endif\n"
-"#endif\n"
-"\n"
-"#ifdef USESHADOWMAPVSDCT\n"
-"uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
-"#endif\n"
-"\n"
-"#if defined(USESHADOWMAP2D)\n"
-"uniform float2 ShadowMap_TextureScale : register(c35),\n"
-"uniform float4 ShadowMap_Parameters : register(c34),\n"
-"#endif\n"
-"\n"
-"out float4 gl_FragData0 : COLOR0,\n"
-"out float4 gl_FragData1 : COLOR1\n"
-")\n"
-"{\n"
-"      // calculate viewspace pixel position\n"
-"      float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
-"      //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
-"      float3 position;\n"
-"#ifdef HLSL\n"
-"      position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
-"#else\n"
-"      position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
-"#endif\n"
-"      position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
-"      // decode viewspace pixel normal\n"
-"      half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
-"      half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
-"      // surfacenormal = pixel normal in viewspace\n"
-"      // LightVector = pixel to light in viewspace\n"
-"      // CubeVector = position in lightspace\n"
-"      // eyevector = pixel to view in viewspace\n"
-"      float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
-"      half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
-"#ifdef USEDIFFUSE\n"
-"      // calculate diffuse shading\n"
-"      half3 lightnormal = half3(normalize(LightPosition - position));\n"
-"      half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
-"#endif\n"
-"#ifdef USESPECULAR\n"
-"      // calculate directional shading\n"
-"      float3 eyevector = position * -1.0;\n"
-"#  ifdef USEEXACTSPECULARMATH\n"
-"      half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
-"#  else\n"
-"      half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
-"      half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
-"#  endif\n"
-"#endif\n"
-"\n"
-"#if defined(USESHADOWMAP2D)\n"
-"      fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
-"#ifdef USESHADOWMAPVSDCT\n"
-", Texture_CubeProjection\n"
-"#endif\n"
-"      ));\n"
-"#endif\n"
-"\n"
-"#ifdef USEDIFFUSE\n"
-"      gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
-"#else\n"
-"      gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
-"#endif\n"
-"#ifdef USESPECULAR\n"
-"      gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
-"#else\n"
-"      gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
-"#endif\n"
-"\n"
-"# ifdef USECUBEFILTER\n"
-"      float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
-"      gl_FragData0.rgb *= cubecolor;\n"
-"      gl_FragData1.rgb *= cubecolor;\n"
-"# endif\n"
-"}\n"
-"#endif // FRAGMENT_SHADER\n"
-"#else // !MODE_DEFERREDLIGHTSOURCE\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef VERTEX_SHADER\n"
-"void main\n"
-"(\n"
-"float4 gl_Vertex : POSITION,\n"
-"uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
-"#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
-"float4 gl_Color : COLOR0,\n"
-"#endif\n"
-"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
-"float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
-"float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
-"float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
-"float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
-"\n"
-"uniform float3 EyePosition : register(c24),\n"
-"uniform float4x4 TexMatrix : register(c0),\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"uniform float4x4 BackgroundTexMatrix : register(c4),\n"
-"#endif\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"uniform float4x4 ModelToLight : register(c20),\n"
-"#endif\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"uniform float3 LightPosition : register(c27),\n"
-"#endif\n"
-"#ifdef MODE_LIGHTDIRECTION\n"
-"uniform float3 LightDir : register(c26),\n"
-"#endif\n"
-"uniform float4 FogPlane : register(c25),\n"
-"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
-"uniform float3 LightPosition : register(c27),\n"
-"#endif\n"
-"#ifdef USESHADOWMAPORTHO\n"
-"uniform float4x4 ShadowMapMatrix : register(c16),\n"
-"#endif\n"
-"#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
-"out float4 gl_FrontColor : COLOR,\n"
-"#endif\n"
-"out float4 TexCoordBoth : TEXCOORD0,\n"
-"#ifdef USELIGHTMAP\n"
-"out float2 TexCoordLightmap : TEXCOORD1,\n"
-"#endif\n"
-"#ifdef USEEYEVECTOR\n"
-"out float3 EyeVector : TEXCOORD2,\n"
-"#endif\n"
-"#ifdef USEREFLECTION\n"
-"out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
-"#endif\n"
-"#ifdef USEFOG\n"
-"out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
-"#endif\n"
-"#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
-"out float3 LightVector : TEXCOORD1,\n"
-"#endif\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"out float3 CubeVector : TEXCOORD3,\n"
-"#endif\n"
-"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
-"out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
-"out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
-"out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
-"#endif\n"
-"#ifdef USESHADOWMAPORTHO\n"
-"out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
-"#endif\n"
-"out float4 gl_Position : POSITION\n"
-")\n"
-"{\n"
-"#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
-"#ifdef HLSL\n"
-"      gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
-"#else\n"
-"      gl_FrontColor = gl_Color; // Cg is forward\n"
-"#endif\n"
-"#endif\n"
-"      // copy the surface texcoord\n"
-"      TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"      TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
-"#endif\n"
-"#ifdef USELIGHTMAP\n"
-"      TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
-"#endif\n"
-"\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"      // transform vertex position into light attenuation/cubemap space\n"
-"      // (-1 to +1 across the light box)\n"
-"      CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
-"\n"
-"# ifdef USEDIFFUSE\n"
-"      // transform unnormalized light direction into tangent space\n"
-"      // (we use unnormalized to ensure that it interpolates correctly and then\n"
-"      //  normalize it per pixel)\n"
-"      float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
-"      LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
-"      LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
-"      LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
-"# endif\n"
-"#endif\n"
-"\n"
-"#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
-"      LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
-"      LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
-"      LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
-"#endif\n"
-"\n"
-"      // transform unnormalized eye direction into tangent space\n"
-"#ifdef USEEYEVECTOR\n"
-"      float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
-"      EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
-"      EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
-"      EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
-"#endif\n"
-"\n"
-"#ifdef USEFOG\n"
-"      EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
-"      EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
-"#endif\n"
-"\n"
-"#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
-"      VectorS = gl_MultiTexCoord1.xyz;\n"
-"      VectorT = gl_MultiTexCoord2.xyz;\n"
-"      VectorR = gl_MultiTexCoord3.xyz;\n"
-"#endif\n"
-"\n"
-"      // transform vertex to camera space, using ftransform to match non-VS rendering\n"
-"      gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
-"\n"
-"#ifdef USESHADOWMAPORTHO\n"
-"      ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
-"#endif\n"
-"\n"
-"#ifdef USEREFLECTION\n"
-"      ModelViewProjectionPosition = gl_Position;\n"
-"#endif\n"
-"}\n"
-"#endif // VERTEX_SHADER\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef FRAGMENT_SHADER\n"
-"void main\n"
-"(\n"
-"#ifdef USEDEFERREDLIGHTMAP\n"
-"#ifdef HLSL\n"
-"float2 Pixel : VPOS,\n"
-"#else\n"
-"float2 Pixel : WPOS,\n"
-"#endif\n"
-"#endif\n"
-"float4 gl_FrontColor : COLOR,\n"
-"float4 TexCoordBoth : TEXCOORD0,\n"
-"#ifdef USELIGHTMAP\n"
-"float2 TexCoordLightmap : TEXCOORD1,\n"
-"#endif\n"
-"#ifdef USEEYEVECTOR\n"
-"float3 EyeVector : TEXCOORD2,\n"
-"#endif\n"
-"#ifdef USEREFLECTION\n"
-"float4 ModelViewProjectionPosition : TEXCOORD3,\n"
-"#endif\n"
-"#ifdef USEFOG\n"
-"float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
-"#endif\n"
-"#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
-"float3 LightVector : TEXCOORD1,\n"
-"#endif\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"float3 CubeVector : TEXCOORD3,\n"
-"#endif\n"
-"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
-"float4 ModelViewPosition : TEXCOORD0,\n"
-"#endif\n"
-"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
-"float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
-"float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
-"float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
-"#endif\n"
-"#ifdef USESHADOWMAPORTHO\n"
-"float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
-"#endif\n"
-"\n"
-"uniform sampler Texture_Normal : register(s0),\n"
-"uniform sampler Texture_Color : register(s1),\n"
-"#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
-"uniform sampler Texture_Gloss : register(s2),\n"
-"#endif\n"
-"#ifdef USEGLOW\n"
-"uniform sampler Texture_Glow : register(s3),\n"
-"#endif\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"uniform sampler Texture_SecondaryNormal : register(s4),\n"
-"uniform sampler Texture_SecondaryColor : register(s5),\n"
-"#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
-"uniform sampler Texture_SecondaryGloss : register(s6),\n"
-"#endif\n"
-"#ifdef USEGLOW\n"
-"uniform sampler Texture_SecondaryGlow : register(s7),\n"
-"#endif\n"
-"#endif\n"
-"#ifdef USECOLORMAPPING\n"
-"uniform sampler Texture_Pants : register(s4),\n"
-"uniform sampler Texture_Shirt : register(s7),\n"
-"#endif\n"
-"#ifdef USEFOG\n"
-"uniform sampler Texture_FogHeightTexture : register(s14),\n"
-"uniform sampler Texture_FogMask : register(s8),\n"
-"#endif\n"
-"#ifdef USELIGHTMAP\n"
-"uniform sampler Texture_Lightmap : register(s9),\n"
-"#endif\n"
-"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
-"uniform sampler Texture_Deluxemap : register(s10),\n"
-"#endif\n"
-"#ifdef USEREFLECTION\n"
-"uniform sampler Texture_Reflection : register(s7),\n"
-"#endif\n"
-"\n"
-"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
-"uniform sampler Texture_ScreenDepth : register(s13),\n"
-"uniform sampler Texture_ScreenNormalMap : register(s14),\n"
-"#endif\n"
-"#ifdef USEDEFERREDLIGHTMAP\n"
-"uniform sampler Texture_ScreenDepth : register(s13),\n"
-"uniform sampler Texture_ScreenNormalMap : register(s14),\n"
-"uniform sampler Texture_ScreenDiffuse : register(s11),\n"
-"uniform sampler Texture_ScreenSpecular : register(s12),\n"
-"#endif\n"
-"\n"
-"#ifdef USECOLORMAPPING\n"
-"uniform half3 Color_Pants : register(c7),\n"
-"uniform half3 Color_Shirt : register(c8),\n"
-"#endif\n"
-"#ifdef USEFOG\n"
-"uniform float3 FogColor : register(c16),\n"
-"uniform float FogRangeRecip : register(c20),\n"
-"uniform float FogPlaneViewDist : register(c19),\n"
-"uniform float FogHeightFade : register(c17),\n"
-"#endif\n"
-"\n"
-"#ifdef USEOFFSETMAPPING\n"
-"uniform float OffsetMapping_Scale : register(c24),\n"
-"#endif\n"
-"\n"
-"#ifdef USEDEFERREDLIGHTMAP\n"
-"uniform half2 PixelToScreenTexCoord : register(c42),\n"
-"uniform half3 DeferredMod_Diffuse : register(c12),\n"
-"uniform half3 DeferredMod_Specular : register(c13),\n"
-"#endif\n"
-"uniform half3 Color_Ambient : register(c3),\n"
-"uniform half3 Color_Diffuse : register(c4),\n"
-"uniform half3 Color_Specular : register(c5),\n"
-"uniform half SpecularPower : register(c36),\n"
-"#ifdef USEGLOW\n"
-"uniform half3 Color_Glow : register(c6),\n"
-"#endif\n"
-"uniform half Alpha : register(c0),\n"
-"#ifdef USEREFLECTION\n"
-"uniform float4 DistortScaleRefractReflect : register(c14),\n"
-"uniform float4 ScreenScaleRefractReflect : register(c32),\n"
-"uniform float4 ScreenCenterRefractReflect : register(c31),\n"
-"uniform half4 ReflectColor : register(c26),\n"
-"#endif\n"
-"#ifdef USEREFLECTCUBE\n"
-"uniform float4x4 ModelToReflectCube : register(c48),\n"
-"uniform sampler Texture_ReflectMask : register(s5),\n"
-"uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
-"#endif\n"
-"#ifdef MODE_LIGHTDIRECTION\n"
-"uniform half3 LightColor : register(c21),\n"
-"#endif\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"uniform half3 LightColor : register(c21),\n"
-"#endif\n"
-"\n"
-"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
-"uniform sampler Texture_Attenuation : register(s9),\n"
-"uniform samplerCUBE Texture_Cube : register(s10),\n"
-"#endif\n"
-"\n"
-"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
-"\n"
-"#ifdef USESHADOWMAP2D\n"
-"# ifdef USESHADOWSAMPLER\n"
-"uniform sampler Texture_ShadowMap2D : register(s15),\n"
-"# else\n"
-"uniform sampler Texture_ShadowMap2D : register(s15),\n"
-"# endif\n"
-"#endif\n"
-"\n"
-"#ifdef USESHADOWMAPVSDCT\n"
-"uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
-"#endif\n"
-"\n"
-"#if defined(USESHADOWMAP2D)\n"
-"uniform float2 ShadowMap_TextureScale : register(c35),\n"
-"uniform float4 ShadowMap_Parameters : register(c34),\n"
-"#endif\n"
-"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
-"\n"
-"out float4 gl_FragColor : COLOR\n"
-")\n"
-"{\n"
-"      float2 TexCoord = TexCoordBoth.xy;\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"      float2 TexCoord2 = TexCoordBoth.zw;\n"
-"#endif\n"
-"#ifdef USEOFFSETMAPPING\n"
-"      // apply offsetmapping\n"
-"      float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
-"#define TexCoord TexCoordOffset\n"
-"#endif\n"
-"\n"
-"      // combine the diffuse textures (base, pants, shirt)\n"
-"      half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
-"#ifdef USEALPHAKILL\n"
-"      if (color.a < 0.5)\n"
-"              discard;\n"
-"#endif\n"
-"      color.a *= Alpha;\n"
-"#ifdef USECOLORMAPPING\n"
-"      color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
-"#endif\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"      half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
-"      //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
-"      //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
-"      color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
-"      color.a = 1.0;\n"
-"      //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
-"#endif\n"
-"\n"
-"      // get the surface normal\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"      half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
-"#else\n"
-"      half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
-"#endif\n"
-"\n"
-"      // get the material colors\n"
-"      half3 diffusetex = color.rgb;\n"
-"#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
-"# ifdef USEVERTEXTEXTUREBLEND\n"
-"      half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
-"# else\n"
-"      half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
-"# endif\n"
-"#endif\n"
-"\n"
-"#ifdef USEREFLECTCUBE\n"
-"      float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
-"      float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
-"      float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
-"      diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
-"#endif\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"      // light source\n"
-"#ifdef USEDIFFUSE\n"
-"      half3 lightnormal = half3(normalize(LightVector));\n"
-"      half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
-"      color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
-"#ifdef USESPECULAR\n"
-"#ifdef USEEXACTSPECULARMATH\n"
-"      half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
-"#else\n"
-"      half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
-"      half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
-"#endif\n"
-"      color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
-"#endif\n"
-"#else\n"
-"      color.rgb = diffusetex * Color_Ambient;\n"
-"#endif\n"
-"      color.rgb *= LightColor;\n"
-"      color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
-"#if defined(USESHADOWMAP2D)\n"
-"      color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
-"#ifdef USESHADOWMAPVSDCT\n"
-", Texture_CubeProjection\n"
-"#endif\n"
-"      ));\n"
-"\n"
-"#endif\n"
-"# ifdef USECUBEFILTER\n"
-"      color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
-"# endif\n"
-"\n"
-"#ifdef USESHADOWMAP2D\n"
-"#ifdef USESHADOWMAPVSDCT\n"
-"//    float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
-"#else\n"
-"//    float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
-"#endif\n"
-"//    color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
-"//    color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
-"//    color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
-"//    color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
-"//    color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
-"//    color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
-"//    color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
-"//    color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
-"//    color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
-"//    color.r = half(shadowmaptc.z);\n"
-"//    color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
-"//    color.r = half(shadowmaptc.z);\n"
-"//    color.r = 1;\n"
-"//    color.rgb = abs(CubeVector);\n"
-"#endif\n"
-"//    color.rgb = half3(1,1,1);\n"
-"#endif // MODE_LIGHTSOURCE\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_LIGHTDIRECTION\n"
-"#define SHADING\n"
-"#ifdef USEDIFFUSE\n"
-"      half3 lightnormal = half3(normalize(LightVector));\n"
-"#endif\n"
-"#define lightcolor LightColor\n"
-"#endif // MODE_LIGHTDIRECTION\n"
-"#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
-"#define SHADING\n"
-"      // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
-"      half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
-"      half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
-"      // convert modelspace light vector to tangentspace\n"
-"      half3 lightnormal;\n"
-"      lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
-"      lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
-"      lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
-"      // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
-"      // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
-"      // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
-"      // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
-"      // to map the luxels to coordinates on the draw surfaces), which also causes\n"
-"      // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
-"      // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
-"      // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
-"      // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
-"      lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
-"#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
-"#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
-"#define SHADING\n"
-"      // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
-"      half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
-"      half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
-"#endif\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_FAKELIGHT\n"
-"#define SHADING\n"
-"half3 lightnormal = half3(normalize(EyeVector));\n"
-"half3 lightcolor = half3(1.0,1.0,1.0);\n"
-"#endif // MODE_FAKELIGHT\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef MODE_LIGHTMAP\n"
-"      color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
-"#endif // MODE_LIGHTMAP\n"
-"#ifdef MODE_VERTEXCOLOR\n"
-"      color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
-"#endif // MODE_VERTEXCOLOR\n"
-"#ifdef MODE_FLATCOLOR\n"
-"      color.rgb = diffusetex * Color_Ambient;\n"
-"#endif // MODE_FLATCOLOR\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"#ifdef SHADING\n"
-"# ifdef USEDIFFUSE\n"
-"      half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
-"#  ifdef USESPECULAR\n"
-"#   ifdef USEEXACTSPECULARMATH\n"
-"      half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
-"#   else\n"
-"      half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
-"      half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
-"#   endif\n"
-"      color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
-"#  else\n"
-"      color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
-"#  endif\n"
-"# else\n"
-"      color.rgb = diffusetex * Color_Ambient;\n"
-"# endif\n"
-"#endif\n"
-"\n"
-"#ifdef USESHADOWMAPORTHO\n"
-"      color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
-"#endif\n"
-"\n"
-"#ifdef USEDEFERREDLIGHTMAP\n"
-"      float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
-"      color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
-"      color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
-"//    color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
-"//    color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
-"#endif\n"
-"\n"
-"#ifdef USEGLOW\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-"      color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
-"#else\n"
-"      color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
-"#endif\n"
-"#endif\n"
-"\n"
-"#ifdef USEFOG\n"
-"      color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
-"#endif\n"
-"\n"
-"      // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
-"#ifdef USEREFLECTION\n"
-"      float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
-"      //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
-"      float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
-"      float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
-"      // FIXME temporary hack to detect the case that the reflection\n"
-"      // gets blackened at edges due to leaving the area that contains actual\n"
-"      // content.\n"
-"      // Remove this 'ack once we have a better way to stop this thing from\n"
-"      // 'appening.\n"
-"      float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
-"      f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
-"      ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
-"      color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
-"#endif\n"
-"\n"
-"      gl_FragColor = float4(color);\n"
-"}\n"
-"#endif // FRAGMENT_SHADER\n"
-"\n"
-"#endif // !MODE_DEFERREDLIGHTSOURCE\n"
-"#endif // !MODE_DEFERREDGEOMETRY\n"
-"#endif // !MODE_WATER\n"
-"#endif // !MODE_REFRACTION\n"
-"#endif // !MODE_BLOOMBLUR\n"
-"#endif // !MODE_GENERIC\n"
-"#endif // !MODE_POSTPROCESS\n"
-"#endif // !MODE_SHOWDEPTH\n"
-"#endif // !MODE_DEPTH_OR_SHADOW\n"
+const char *builtinhlslshaderstring =
+#include "shader_hlsl.h"
 ;
 
 char *glslshaderstring = NULL;
-char *cgshaderstring = NULL;
 char *hlslshaderstring = NULL;
 
 //=======================================================================================================================================================
@@ -3354,6 +648,7 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
        {"#define USEFOGINSIDE\n", " foginside"},
        {"#define USEFOGOUTSIDE\n", " fogoutside"},
        {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
+       {"#define USEFOGALPHAHACK\n", " fogalphahack"},
        {"#define USEGAMMARAMPS\n", " gammaramps"},
        {"#define USECUBEFILTER\n", " cubefilter"},
        {"#define USEGLOW\n", " glow"},
@@ -3373,6 +668,9 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
        {"#define USEALPHAKILL\n", " alphakill"},
        {"#define USEREFLECTCUBE\n", " reflectcube"},
        {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
+       {"#define USEBOUNCEGRID\n", " bouncegrid"},
+       {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
+       {"#define USETRIPPY\n", " trippy"},
 };
 
 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
@@ -3396,29 +694,6 @@ shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
        {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
 };
 
-#ifdef SUPPORTCG
-shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
-{
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
-       {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
-};
-#endif
-
-#ifdef SUPPORTD3D
 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
 {
        {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
@@ -3438,7 +713,6 @@ shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
        {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
        {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
 };
-#endif
 
 struct r_glsl_permutation_s;
 typedef struct r_glsl_permutation_s
@@ -3452,6 +726,37 @@ typedef struct r_glsl_permutation_s
        qboolean compiled;
        /// 0 if compilation failed
        int program;
+       // texture units assigned to each detected uniform
+       int tex_Texture_First;
+       int tex_Texture_Second;
+       int tex_Texture_GammaRamps;
+       int tex_Texture_Normal;
+       int tex_Texture_Color;
+       int tex_Texture_Gloss;
+       int tex_Texture_Glow;
+       int tex_Texture_SecondaryNormal;
+       int tex_Texture_SecondaryColor;
+       int tex_Texture_SecondaryGloss;
+       int tex_Texture_SecondaryGlow;
+       int tex_Texture_Pants;
+       int tex_Texture_Shirt;
+       int tex_Texture_FogHeightTexture;
+       int tex_Texture_FogMask;
+       int tex_Texture_Lightmap;
+       int tex_Texture_Deluxemap;
+       int tex_Texture_Attenuation;
+       int tex_Texture_Cube;
+       int tex_Texture_Refraction;
+       int tex_Texture_Reflection;
+       int tex_Texture_ShadowMap2D;
+       int tex_Texture_CubeProjection;
+       int tex_Texture_ScreenDepth;
+       int tex_Texture_ScreenNormalMap;
+       int tex_Texture_ScreenDiffuse;
+       int tex_Texture_ScreenSpecular;
+       int tex_Texture_ReflectMask;
+       int tex_Texture_ReflectCube;
+       int tex_Texture_BounceGrid;
        /// locations of detected uniforms in program object, or -1 if not found
        int loc_Texture_First;
        int loc_Texture_Second;
@@ -3482,6 +787,7 @@ typedef struct r_glsl_permutation_s
        int loc_Texture_ScreenSpecular;
        int loc_Texture_ReflectMask;
        int loc_Texture_ReflectCube;
+       int loc_Texture_BounceGrid;
        int loc_Alpha;
        int loc_BloomBlur_Parameters;
        int loc_ClientTime;
@@ -3506,7 +812,7 @@ typedef struct r_glsl_permutation_s
        int loc_LightColor;
        int loc_LightDir;
        int loc_LightPosition;
-       int loc_OffsetMapping_Scale;
+       int loc_OffsetMapping_ScaleSteps;
        int loc_PixelSize;
        int loc_ReflectColor;
        int loc_ReflectFactor;
@@ -3535,6 +841,8 @@ typedef struct r_glsl_permutation_s
        int loc_ShadowMapMatrix;
        int loc_BloomColorSubtract;
        int loc_NormalmapScrollBlend;
+       int loc_BounceGridMatrix;
+       int loc_BounceGridIntensity;
 }
 r_glsl_permutation_t;
 
@@ -3550,9 +858,10 @@ enum
        SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
        SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
        SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
-       SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
+       SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
+       SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
 };
-#define SHADERSTATICPARMS_COUNT 6
+#define SHADERSTATICPARMS_COUNT 7
 
 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
 static int shaderstaticparms_count = 0;
@@ -3568,6 +877,8 @@ qboolean R_CompileShader_CheckStaticParms(void)
        // detect all
        if (r_glsl_saturation_redcompensate.integer)
                R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
+       if (r_glsl_vertextextureblend_usebothalphas.integer)
+               R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
        if (r_shadow_glossexact.integer)
                R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
        if (r_glsl_postprocess.integer)
@@ -3600,6 +911,7 @@ void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
        R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
        R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
        R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
+       R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
 }
 
 /// information about each possible shader permutation
@@ -3666,6 +978,7 @@ static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
 {
        int i;
+       int sampler;
        shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
        char *vertexstring, *geometrystring, *fragmentstring;
        char permutationname[256];
@@ -3688,6 +1001,17 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode
 
        strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
 
+       // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
+       if(vid.support.gl20shaders130)
+       {
+               vertstrings_list[vertstrings_count++] = "#version 130\n";
+               geomstrings_list[geomstrings_count++] = "#version 130\n";
+               fragstrings_list[fragstrings_count++] = "#version 130\n";
+               vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
+               geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
+               fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
+       }
+
        // the first pretext is which type of shader to compile as
        // (later these will all be bound together as a program object)
        vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
@@ -3747,124 +1071,159 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode
        if (p->program)
        {
                CHECKGLERROR
-               qglUseProgramObjectARB(p->program);CHECKGLERROR
+               qglUseProgram(p->program);CHECKGLERROR
                // look up all the uniform variable names we care about, so we don't
                // have to look them up every time we set them
 
-               p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
-               p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
-               p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
-               p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
-               p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
-               p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
-               p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
-               p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
-               p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
-               p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
-               p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
-               p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
-               p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
-               p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
-               p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
-               p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
-               p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
-               p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
-               p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
-               p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
-               p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
-               p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
-               p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
-               p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
-               p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
-               p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
-               p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
-               p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
-               p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
-               p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
-               p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
-               p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
-               p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
-               p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
-               p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
-               p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
-               p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
-               p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
-               p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
-               p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
-               p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
-               p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
-               p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
-               p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
-               p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
-               p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
-               p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
-               p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
-               p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
-               p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
-               p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
-               p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
-               p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
-               p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
-               p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
-               p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
-               p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
-               p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
-               p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
-               p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
-               p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
-               p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
-               p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
-               p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
-               p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
-               p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
-               p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
-               p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
-               p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
-               p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
-               p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
-               p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
-               p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
-               p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
-               p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
-               p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
-               p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
-               p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
-               p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
-               p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
-               p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
-               p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
+               p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
+               p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
+               p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
+               p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
+               p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
+               p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
+               p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
+               p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
+               p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
+               p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
+               p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
+               p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
+               p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
+               p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
+               p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
+               p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
+               p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
+               p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
+               p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
+               p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
+               p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
+               p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
+               p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
+               p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
+               p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
+               p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
+               p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
+               p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
+               p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
+               p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
+               p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
+               p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
+               p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
+               p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
+               p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
+               p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
+               p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
+               p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
+               p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
+               p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
+               p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
+               p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
+               p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
+               p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
+               p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
+               p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
+               p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
+               p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
+               p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
+               p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
+               p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
+               p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
+               p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
+               p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
+               p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
+               p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
+               p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
+               p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
+               p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
+               p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
+               p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
+               p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
+               p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
+               p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
+               p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
+               p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
+               p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
+               p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
+               p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
+               p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
+               p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
+               p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
+               p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
+               p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
+               p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
+               p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
+               p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
+               p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
+               p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
+               p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
+               p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
+               p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
+               p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
+               p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
+               p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
                // initialize the samplers to refer to the texture units we use
-               if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
-               if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
-               if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
-               if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
-               if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
-               if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
-               if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
-               if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
-               if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
-               if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
-               if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
-               if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
-               if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
-               if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
-               if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
-               if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
-               if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
-               if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
-               if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
-               if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
-               if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
-               if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
-               if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
-               if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
-               if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
-               if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
-               if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
-               if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
-               if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
+               p->tex_Texture_First = -1;
+               p->tex_Texture_Second = -1;
+               p->tex_Texture_GammaRamps = -1;
+               p->tex_Texture_Normal = -1;
+               p->tex_Texture_Color = -1;
+               p->tex_Texture_Gloss = -1;
+               p->tex_Texture_Glow = -1;
+               p->tex_Texture_SecondaryNormal = -1;
+               p->tex_Texture_SecondaryColor = -1;
+               p->tex_Texture_SecondaryGloss = -1;
+               p->tex_Texture_SecondaryGlow = -1;
+               p->tex_Texture_Pants = -1;
+               p->tex_Texture_Shirt = -1;
+               p->tex_Texture_FogHeightTexture = -1;
+               p->tex_Texture_FogMask = -1;
+               p->tex_Texture_Lightmap = -1;
+               p->tex_Texture_Deluxemap = -1;
+               p->tex_Texture_Attenuation = -1;
+               p->tex_Texture_Cube = -1;
+               p->tex_Texture_Refraction = -1;
+               p->tex_Texture_Reflection = -1;
+               p->tex_Texture_ShadowMap2D = -1;
+               p->tex_Texture_CubeProjection = -1;
+               p->tex_Texture_ScreenDepth = -1;
+               p->tex_Texture_ScreenNormalMap = -1;
+               p->tex_Texture_ScreenDiffuse = -1;
+               p->tex_Texture_ScreenSpecular = -1;
+               p->tex_Texture_ReflectMask = -1;
+               p->tex_Texture_ReflectCube = -1;
+               p->tex_Texture_BounceGrid = -1;
+               sampler = 0;
+               if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
+               if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
+               if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
+               if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
+               if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
+               if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
+               if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
+               if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
+               if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
+               if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
+               if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
+               if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
+               if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
+               if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
+               if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
+               if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
+               if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
+               if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
+               if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
+               if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
+               if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
+               if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
+               if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
+               if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
+               if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
+               if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
+               if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
+               if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
+               if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
+               if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
                CHECKGLERROR
-               Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
+               Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
        }
        else
                Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
@@ -3909,531 +1268,19 @@ void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutatio
                                {
                                        //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
                                        r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
-                                       qglUseProgramObjectARB(0);CHECKGLERROR
+                                       qglUseProgram(0);CHECKGLERROR
                                        return; // no bit left to clear, entire mode is broken
                                }
                        }
                }
                CHECKGLERROR
-               qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
-       }
-       if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
-       if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
-       if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
-}
-
-#ifdef SUPPORTCG
-#include <Cg/cgGL.h>
-struct r_cg_permutation_s;
-typedef struct r_cg_permutation_s
-{
-       /// hash lookup data
-       struct r_cg_permutation_s *hashnext;
-       unsigned int mode;
-       unsigned int permutation;
-
-       /// indicates if we have tried compiling this permutation already
-       qboolean compiled;
-       /// 0 if compilation failed
-       CGprogram vprogram;
-       CGprogram fprogram;
-       /// locations of detected parameters in programs, or NULL if not found
-       CGparameter vp_EyePosition;
-       CGparameter vp_FogPlane;
-       CGparameter vp_LightDir;
-       CGparameter vp_LightPosition;
-       CGparameter vp_ModelToLight;
-       CGparameter vp_TexMatrix;
-       CGparameter vp_BackgroundTexMatrix;
-       CGparameter vp_ModelViewProjectionMatrix;
-       CGparameter vp_ModelViewMatrix;
-       CGparameter vp_ShadowMapMatrix;
-
-       CGparameter fp_Texture_First;
-       CGparameter fp_Texture_Second;
-       CGparameter fp_Texture_GammaRamps;
-       CGparameter fp_Texture_Normal;
-       CGparameter fp_Texture_Color;
-       CGparameter fp_Texture_Gloss;
-       CGparameter fp_Texture_Glow;
-       CGparameter fp_Texture_SecondaryNormal;
-       CGparameter fp_Texture_SecondaryColor;
-       CGparameter fp_Texture_SecondaryGloss;
-       CGparameter fp_Texture_SecondaryGlow;
-       CGparameter fp_Texture_Pants;
-       CGparameter fp_Texture_Shirt;
-       CGparameter fp_Texture_FogHeightTexture;
-       CGparameter fp_Texture_FogMask;
-       CGparameter fp_Texture_Lightmap;
-       CGparameter fp_Texture_Deluxemap;
-       CGparameter fp_Texture_Attenuation;
-       CGparameter fp_Texture_Cube;
-       CGparameter fp_Texture_Refraction;
-       CGparameter fp_Texture_Reflection;
-       CGparameter fp_Texture_ShadowMap2D;
-       CGparameter fp_Texture_CubeProjection;
-       CGparameter fp_Texture_ScreenDepth;
-       CGparameter fp_Texture_ScreenNormalMap;
-       CGparameter fp_Texture_ScreenDiffuse;
-       CGparameter fp_Texture_ScreenSpecular;
-       CGparameter fp_Texture_ReflectMask;
-       CGparameter fp_Texture_ReflectCube;
-       CGparameter fp_Alpha;
-       CGparameter fp_BloomBlur_Parameters;
-       CGparameter fp_ClientTime;
-       CGparameter fp_Color_Ambient;
-       CGparameter fp_Color_Diffuse;
-       CGparameter fp_Color_Specular;
-       CGparameter fp_Color_Glow;
-       CGparameter fp_Color_Pants;
-       CGparameter fp_Color_Shirt;
-       CGparameter fp_DeferredColor_Ambient;
-       CGparameter fp_DeferredColor_Diffuse;
-       CGparameter fp_DeferredColor_Specular;
-       CGparameter fp_DeferredMod_Diffuse;
-       CGparameter fp_DeferredMod_Specular;
-       CGparameter fp_DistortScaleRefractReflect;
-       CGparameter fp_EyePosition;
-       CGparameter fp_FogColor;
-       CGparameter fp_FogHeightFade;
-       CGparameter fp_FogPlane;
-       CGparameter fp_FogPlaneViewDist;
-       CGparameter fp_FogRangeRecip;
-       CGparameter fp_LightColor;
-       CGparameter fp_LightDir;
-       CGparameter fp_LightPosition;
-       CGparameter fp_OffsetMapping_Scale;
-       CGparameter fp_PixelSize;
-       CGparameter fp_ReflectColor;
-       CGparameter fp_ReflectFactor;
-       CGparameter fp_ReflectOffset;
-       CGparameter fp_RefractColor;
-       CGparameter fp_Saturation;
-       CGparameter fp_ScreenCenterRefractReflect;
-       CGparameter fp_ScreenScaleRefractReflect;
-       CGparameter fp_ScreenToDepth;
-       CGparameter fp_ShadowMap_Parameters;
-       CGparameter fp_ShadowMap_TextureScale;
-       CGparameter fp_SpecularPower;
-       CGparameter fp_UserVec1;
-       CGparameter fp_UserVec2;
-       CGparameter fp_UserVec3;
-       CGparameter fp_UserVec4;
-       CGparameter fp_ViewTintColor;
-       CGparameter fp_ViewToLight;
-       CGparameter fp_PixelToScreenTexCoord;
-       CGparameter fp_ModelToReflectCube;
-       CGparameter fp_BloomColorSubtract;
-       CGparameter fp_NormalmapScrollBlend;
-}
-r_cg_permutation_t;
-
-/// information about each possible shader permutation
-r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
-/// currently selected permutation
-r_cg_permutation_t *r_cg_permutation;
-/// storage for permutations linked in the hash table
-memexpandablearray_t r_cg_permutationarray;
-
-#define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
-
-static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
-{
-       //unsigned int hashdepth = 0;
-       unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
-       r_cg_permutation_t *p;
-       for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
-       {
-               if (p->mode == mode && p->permutation == permutation)
-               {
-                       //if (hashdepth > 10)
-                       //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
-                       return p;
-               }
-               //hashdepth++;
+               qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
        }
-       p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
-       p->mode = mode;
-       p->permutation = permutation;
-       p->hashnext = r_cg_permutationhash[mode][hashindex];
-       r_cg_permutationhash[mode][hashindex] = p;
-       //if (hashdepth > 10)
-       //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
-       return p;
+       if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
+       if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
+       if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
 }
 
-static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
-{
-       char *shaderstring;
-       if (!filename || !filename[0])
-               return NULL;
-       if (!strcmp(filename, "cg/default.cg"))
-       {
-               if (!cgshaderstring)
-               {
-                       cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
-                       if (cgshaderstring)
-                               Con_DPrintf("Loading shaders from file %s...\n", filename);
-                       else
-                               cgshaderstring = (char *)builtincgshaderstring;
-               }
-               shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
-               memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
-               return shaderstring;
-       }
-       shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
-       if (shaderstring)
-       {
-               if (printfromdisknotice)
-                       Con_DPrintf("from disk %s... ", filename);
-               return shaderstring;
-       }
-       return shaderstring;
-}
-
-static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
-{
-       // TODO: load or create .fp and .vp shader files
-}
-
-static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
-{
-       int i;
-       shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
-       int vertstring_length = 0;
-       int geomstring_length = 0;
-       int fragstring_length = 0;
-       char *t;
-       char *vertexstring, *geometrystring, *fragmentstring;
-       char *vertstring, *geomstring, *fragstring;
-       char permutationname[256];
-       char cachename[256];
-       CGprofile vertexProfile;
-       CGprofile fragmentProfile;
-       int vertstrings_count = 0;
-       int geomstrings_count = 0;
-       int fragstrings_count = 0;
-       const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
-       const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
-       const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
-
-       if (p->compiled)
-               return;
-       p->compiled = true;
-       p->vprogram = NULL;
-       p->fprogram = NULL;
-
-       permutationname[0] = 0;
-       cachename[0] = 0;
-       vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
-       geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
-       fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
-
-       strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
-       strlcat(cachename, "cg/", sizeof(cachename));
-
-       // the first pretext is which type of shader to compile as
-       // (later these will all be bound together as a program object)
-       vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
-       geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
-       fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
-
-       // the second pretext is the mode (for example a light source)
-       vertstrings_list[vertstrings_count++] = modeinfo->pretext;
-       geomstrings_list[geomstrings_count++] = modeinfo->pretext;
-       fragstrings_list[fragstrings_count++] = modeinfo->pretext;
-       strlcat(permutationname, modeinfo->name, sizeof(permutationname));
-       strlcat(cachename, modeinfo->name, sizeof(cachename));
-
-       // now add all the permutation pretexts
-       for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
-       {
-               if (permutation & (1<<i))
-               {
-                       vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
-                       geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
-                       fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
-                       strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
-                       strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
-               }
-               else
-               {
-                       // keep line numbers correct
-                       vertstrings_list[vertstrings_count++] = "\n";
-                       geomstrings_list[geomstrings_count++] = "\n";
-                       fragstrings_list[fragstrings_count++] = "\n";
-               }
-       }
-
-       // add static parms
-       R_CompileShader_AddStaticParms(mode, permutation);
-       memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
-       vertstrings_count += shaderstaticparms_count;
-       memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
-       geomstrings_count += shaderstaticparms_count;
-       memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
-       fragstrings_count += shaderstaticparms_count;
-
-       // replace spaces in the cachename with _ characters
-       for (i = 0;cachename[i];i++)
-               if (cachename[i] == ' ')
-                       cachename[i] = '_';
-
-       // now append the shader text itself
-       vertstrings_list[vertstrings_count++] = vertexstring;
-       geomstrings_list[geomstrings_count++] = geometrystring;
-       fragstrings_list[fragstrings_count++] = fragmentstring;
-
-       // if any sources were NULL, clear the respective list
-       if (!vertexstring)
-               vertstrings_count = 0;
-       if (!geometrystring)
-               geomstrings_count = 0;
-       if (!fragmentstring)
-               fragstrings_count = 0;
-
-       vertstring_length = 0;
-       for (i = 0;i < vertstrings_count;i++)
-               vertstring_length += strlen(vertstrings_list[i]);
-       vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
-       for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
-               memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
-
-       geomstring_length = 0;
-       for (i = 0;i < geomstrings_count;i++)
-               geomstring_length += strlen(geomstrings_list[i]);
-       geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
-       for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
-               memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
-
-       fragstring_length = 0;
-       for (i = 0;i < fragstrings_count;i++)
-               fragstring_length += strlen(fragstrings_list[i]);
-       fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
-       for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
-               memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
-
-       CHECKGLERROR
-       CHECKCGERROR
-       //vertexProfile = CG_PROFILE_ARBVP1;
-       //fragmentProfile = CG_PROFILE_ARBFP1;
-       vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
-       fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
-       //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
-       //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
-       //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
-       CHECKGLERROR
-
-       // try to load the cached shader, or generate one
-       R_CG_CacheShader(p, cachename, vertstring, fragstring);
-
-       // if caching failed, do a dynamic compile for now
-       CHECKCGERROR
-       if (vertstring[0] && !p->vprogram)
-               p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
-       CHECKCGERROR
-       if (fragstring[0] && !p->fprogram)
-               p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
-       CHECKCGERROR
-
-       // look up all the uniform variable names we care about, so we don't
-       // have to look them up every time we set them
-       if (p->vprogram)
-       {
-               CHECKCGERROR
-               cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
-               cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
-               p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
-               p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
-               p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
-               p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
-               p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
-               p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
-               p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
-               p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
-               p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
-               p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
-               CHECKCGERROR
-       }
-       if (p->fprogram)
-       {
-               CHECKCGERROR
-               cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
-               cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
-               p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
-               p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
-               p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
-               p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
-               p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
-               p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
-               p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
-               p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
-               p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
-               p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
-               p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
-               p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
-               p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
-               p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
-               p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
-               p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
-               p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
-               p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
-               p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
-               p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
-               p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
-               p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
-               p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
-               p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
-               p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
-               p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
-               p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
-               p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
-               p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
-               p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
-               p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
-               p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
-               p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
-               p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
-               p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
-               p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
-               p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
-               p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
-               p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
-               p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
-               p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
-               p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
-               p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
-               p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
-               p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
-               p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
-               p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
-               p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
-               p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
-               p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
-               p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
-               p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
-               p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
-               p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
-               p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
-               p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
-               p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
-               p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
-               p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
-               p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
-               p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
-               p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
-               p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
-               p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
-               p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
-               p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
-               p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
-               p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
-               p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
-               p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
-               p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
-               p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
-               p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
-               p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
-               p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
-               p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
-               CHECKCGERROR
-       }
-
-       if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
-               Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
-       else
-               Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
-
-       // free the strings
-       if (vertstring)
-               Mem_Free(vertstring);
-       if (geomstring)
-               Mem_Free(geomstring);
-       if (fragstring)
-               Mem_Free(fragstring);
-       if (vertexstring)
-               Mem_Free(vertexstring);
-       if (geometrystring)
-               Mem_Free(geometrystring);
-       if (fragmentstring)
-               Mem_Free(fragmentstring);
-}
-
-void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
-{
-       r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
-       CHECKGLERROR
-       CHECKCGERROR
-       if (r_cg_permutation != perm)
-       {
-               r_cg_permutation = perm;
-               if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
-               {
-                       if (!r_cg_permutation->compiled)
-                               R_CG_CompilePermutation(perm, mode, permutation);
-                       if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
-                       {
-                               // remove features until we find a valid permutation
-                               int i;
-                               for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
-                               {
-                                       // reduce i more quickly whenever it would not remove any bits
-                                       int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
-                                       if (!(permutation & j))
-                                               continue;
-                                       permutation -= j;
-                                       r_cg_permutation = R_CG_FindPermutation(mode, permutation);
-                                       if (!r_cg_permutation->compiled)
-                                               R_CG_CompilePermutation(perm, mode, permutation);
-                                       if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
-                                               break;
-                               }
-                               if (i >= SHADERPERMUTATION_COUNT)
-                               {
-                                       //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
-                                       r_cg_permutation = R_CG_FindPermutation(mode, permutation);
-                                       return; // no bit left to clear, entire mode is broken
-                               }
-                       }
-               }
-               CHECKGLERROR
-               CHECKCGERROR
-               if (r_cg_permutation->vprogram)
-               {
-                       cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
-                       cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
-                       cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
-               }
-               else
-               {
-                       cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
-                       cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
-               }
-               if (r_cg_permutation->fprogram)
-               {
-                       cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
-                       cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
-                       cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
-               }
-               else
-               {
-                       cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
-                       cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
-               }
-       }
-       CHECKCGERROR
-       if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
-       if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
-       if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
-}
-
-void CG_BindTexture(CGparameter param, rtexture_t *tex)
-{
-       cgGLSetTextureParameter(param, R_GetTexture(tex));
-       cgGLEnableTextureParameter(param);
-}
-#endif
-
 #ifdef SUPPORTD3D
 
 #ifdef SUPPORTD3D
@@ -4499,7 +1346,7 @@ typedef enum D3DPSREGISTER_e
        D3DPSREGISTER_LightColor = 21,
        D3DPSREGISTER_LightDir = 22, // unused
        D3DPSREGISTER_LightPosition = 23,
-       D3DPSREGISTER_OffsetMapping_Scale = 24,
+       D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
        D3DPSREGISTER_PixelSize = 25,
        D3DPSREGISTER_ReflectColor = 26,
        D3DPSREGISTER_ReflectFactor = 27,
@@ -4571,7 +1418,7 @@ static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
                        if (hlslshaderstring)
                                Con_DPrintf("Loading shaders from file %s...\n", filename);
                        else
-                               hlslshaderstring = (char *)builtincgshaderstring;
+                               hlslshaderstring = (char *)builtinhlslshaderstring;
                }
                shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
                memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
@@ -4919,7 +1766,7 @@ void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutatio
                                }
                                if (i >= SHADERPERMUTATION_COUNT)
                                {
-                                       //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
+                                       //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
                                        r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
                                        return; // no bit left to clear, entire mode is broken
                                }
@@ -4936,10 +1783,10 @@ void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutatio
 
 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
 {
-       DPSOFTRAST_SetShader(mode, permutation);
-       DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
-       DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
-       DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
+       DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
+       DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
+       DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
+       DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
 }
 
 void R_GLSL_Restart_f(void)
@@ -4948,10 +1795,7 @@ void R_GLSL_Restart_f(void)
        if (glslshaderstring && glslshaderstring != builtinshaderstring)
                Mem_Free(glslshaderstring);
        glslshaderstring = NULL;
-       if (cgshaderstring && cgshaderstring != builtincgshaderstring)
-               Mem_Free(cgshaderstring);
-       cgshaderstring = NULL;
-       if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
+       if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
                Mem_Free(hlslshaderstring);
        hlslshaderstring = NULL;
        switch(vid.renderpath)
@@ -4961,10 +1805,6 @@ void R_GLSL_Restart_f(void)
                {
                        r_hlsl_permutation_t *p;
                        r_hlsl_permutation = NULL;
-//                     cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
-//                     cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
-//                     cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
-//                     cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
                        limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
                        for (i = 0;i < limit;i++)
                        {
@@ -4988,6 +1828,7 @@ void R_GLSL_Restart_f(void)
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES2:
                {
                        r_glsl_permutation_t *p;
                        r_glsl_permutation = NULL;
@@ -5003,33 +1844,9 @@ void R_GLSL_Restart_f(void)
                        memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
                }
                break;
-       case RENDERPATH_CGGL:
-#ifdef SUPPORTCG
-               {
-                       r_cg_permutation_t *p;
-                       r_cg_permutation = NULL;
-                       cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
-                       cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
-                       cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
-                       cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
-                       limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
-                       for (i = 0;i < limit;i++)
-                       {
-                               if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
-                               {
-                                       if (p->vprogram)
-                                               cgDestroyProgram(p->vprogram);
-                                       if (p->fprogram)
-                                               cgDestroyProgram(p->fprogram);
-                                       Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
-                               }
-                       }
-                       memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
-               }
-#endif
-               break;
-       case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                break;
        case RENDERPATH_SOFT:
                break;
@@ -5058,26 +1875,6 @@ void R_GLSL_DumpShader_f(void)
        else
                Con_Printf("failed to write to glsl/default.glsl\n");
 
-#ifdef SUPPORTCG
-       file = FS_OpenRealFile("cg/default.cg", "w", false);
-       if (file)
-       {
-               FS_Print(file, "/* The engine may define the following macros:\n");
-               FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
-               for (i = 0;i < SHADERMODE_COUNT;i++)
-                       FS_Print(file, cgshadermodeinfo[i].pretext);
-               for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
-                       FS_Print(file, shaderpermutationinfo[i].pretext);
-               FS_Print(file, "*/\n");
-               FS_Print(file, builtincgshaderstring);
-               FS_Close(file);
-               Con_Printf("cg/default.cg written\n");
-       }
-       else
-               Con_Printf("failed to write to cg/default.cg\n");
-#endif
-
-#ifdef SUPPORTD3D
        file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
        if (file)
        {
@@ -5088,24 +1885,39 @@ void R_GLSL_DumpShader_f(void)
                for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
                        FS_Print(file, shaderpermutationinfo[i].pretext);
                FS_Print(file, "*/\n");
-               FS_Print(file, builtincgshaderstring);
+               FS_Print(file, builtinhlslshaderstring);
                FS_Close(file);
                Con_Printf("hlsl/default.hlsl written\n");
        }
        else
                Con_Printf("failed to write to hlsl/default.hlsl\n");
-#endif
 }
 
-void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
+void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean notrippy)
 {
+       unsigned int permutation = 0;
+       if (r_trippy.integer && !notrippy)
+               permutation |= SHADERPERMUTATION_TRIPPY;
+       permutation |= SHADERPERMUTATION_VIEWTINT;
+       if (first)
+               permutation |= SHADERPERMUTATION_DIFFUSE;
+       if (second)
+               permutation |= SHADERPERMUTATION_SPECULAR;
+       if (texturemode == GL_MODULATE)
+               permutation |= SHADERPERMUTATION_COLORMAPPING;
+       else if (texturemode == GL_ADD)
+               permutation |= SHADERPERMUTATION_GLOW;
+       else if (texturemode == GL_DECAL)
+               permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
        if (!second)
                texturemode = GL_MODULATE;
+       if (vid.allowalphatocoverage)
+               GL_AlphaToCoverage(false);
        switch (vid.renderpath)
        {
        case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
-               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))));
+               R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
                R_Mesh_TexBind(GL20TU_FIRST , first );
                R_Mesh_TexBind(GL20TU_SECOND, second);
 #endif
@@ -5117,19 +1929,13 @@ void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemod
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
        case RENDERPATH_GL20:
-               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))));
-               R_Mesh_TexBind(GL20TU_FIRST , first );
-               R_Mesh_TexBind(GL20TU_SECOND, second);
-               break;
-       case RENDERPATH_CGGL:
-#ifdef SUPPORTCG
-               CHECKCGERROR
-               R_SetupShader_SetPermutationCG(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))));
-               if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
-#endif
+       case RENDERPATH_GLES2:
+               R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
+               R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
+               R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
                break;
        case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                R_Mesh_TexBind(0, first );
                R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
                R_Mesh_TexBind(1, second);
@@ -5140,20 +1946,25 @@ void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemod
                R_Mesh_TexBind(0, first );
                break;
        case RENDERPATH_SOFT:
-               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))));
+               R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
                R_Mesh_TexBind(GL20TU_FIRST , first );
                R_Mesh_TexBind(GL20TU_SECOND, second);
                break;
        }
 }
 
-void R_SetupShader_DepthOrShadow(void)
+void R_SetupShader_DepthOrShadow(qboolean notrippy)
 {
+       unsigned int permutation = 0;
+       if (r_trippy.integer && !notrippy)
+               permutation |= SHADERPERMUTATION_TRIPPY;
+       if (vid.allowalphatocoverage)
+               GL_AlphaToCoverage(false);
        switch (vid.renderpath)
        {
        case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
-               R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
+               R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
 #endif
                break;
        case RENDERPATH_D3D10:
@@ -5163,14 +1974,11 @@ void R_SetupShader_DepthOrShadow(void)
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
        case RENDERPATH_GL20:
-               R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
-               break;
-       case RENDERPATH_CGGL:
-#ifdef SUPPORTCG
-               R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
-#endif
+       case RENDERPATH_GLES2:
+               R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
                break;
        case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                R_Mesh_TexBind(0, 0);
                R_Mesh_TexBind(1, 0);
                break;
@@ -5178,18 +1986,25 @@ void R_SetupShader_DepthOrShadow(void)
                R_Mesh_TexBind(0, 0);
                break;
        case RENDERPATH_SOFT:
-               R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
+               R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
                break;
        }
 }
 
-void R_SetupShader_ShowDepth(void)
+void R_SetupShader_ShowDepth(qboolean notrippy)
 {
+       int permutation = 0;
+       if (r_trippy.integer && !notrippy)
+               permutation |= SHADERPERMUTATION_TRIPPY;
+       if (r_trippy.integer)
+               permutation |= SHADERPERMUTATION_TRIPPY;
+       if (vid.allowalphatocoverage)
+               GL_AlphaToCoverage(false);
        switch (vid.renderpath)
        {
        case RENDERPATH_D3D9:
 #ifdef SUPPORTHLSL
-               R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
+               R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
 #endif
                break;
        case RENDERPATH_D3D10:
@@ -5199,19 +2014,16 @@ void R_SetupShader_ShowDepth(void)
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
        case RENDERPATH_GL20:
-               R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
-               break;
-       case RENDERPATH_CGGL:
-#ifdef SUPPORTCG
-               R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
-#endif
+       case RENDERPATH_GLES2:
+               R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
                break;
        case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                break;
        case RENDERPATH_GL11:
                break;
        case RENDERPATH_SOFT:
-               R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
+               R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
                break;
        }
 }
@@ -5240,102 +2052,54 @@ extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
-static qboolean R_BlendFuncAllowsColormod(int src, int dst)
+
+#define BLENDFUNC_ALLOWS_COLORMOD      1
+#define BLENDFUNC_ALLOWS_FOG           2
+#define BLENDFUNC_ALLOWS_FOG_HACK0     4
+#define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
+#define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
+static int R_BlendFuncFlags(int src, int dst)
 {
+       int r = 0;
+
        // a blendfunc allows colormod if:
        // a) it can never keep the destination pixel invariant, or
        // b) it can keep the destination pixel invariant, and still can do so if colormodded
        // this is to prevent unintended side effects from colormod
 
-       // in formulas:
-       // IF there is a (s, sa) for which for all (d, da),
-       //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
-       // THEN, for this (s, sa) and all (colormod, d, da):
-       //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
-       // OBVIOUSLY, this means that
-       //   s*colormod * src(s*colormod, d, sa, da) = 0
-       //   dst(s*colormod, d, sa, da)              = 1
-
-       // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
-
-       // main condition to leave dst color invariant:
-       //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
-       //   src == GL_ZERO:
-       //     s * 0 + d * dst(s, d, sa, da) == d
-       //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
-       //       => colormod is a problem for GL_SRC_COLOR only
-       //   src == GL_ONE:
-       //     s + d * dst(s, d, sa, da) == d
-       //       => s == 0
-       //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
-       //       => colormod is never problematic for these
-       //   src == GL_SRC_COLOR:
-       //     s*s + d * dst(s, d, sa, da) == d
-       //       => s == 0
-       //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
-       //       => colormod is never problematic for these
-       //   src == GL_ONE_MINUS_SRC_COLOR:
-       //     s*(1-s) + d * dst(s, d, sa, da) == d
-       //       => s == 0 or s == 1
-       //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
-       //       => colormod is a problem for GL_SRC_COLOR only
-       //   src == GL_DST_COLOR
-       //     s*d + d * dst(s, d, sa, da) == d
-       //       => s == 1
-       //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
-       //       => colormod is always a problem
-       //     or
-       //       => s == 0
-       //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
-       //       => colormod is never problematic for these
-       //       => BUT, we do not know s! We must assume it is problematic
-       //       then... except in GL_ONE case, where we know all invariant
-       //       cases are fine
-       //   src == GL_ONE_MINUS_DST_COLOR
-       //     s*(1-d) + d * dst(s, d, sa, da) == d
-       //       => s == 0 (1-d is impossible to handle for our desired result)
-       //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
-       //       => colormod is never problematic for these
-       //   src == GL_SRC_ALPHA
-       //     s*sa + d * dst(s, d, sa, da) == d
-       //       => s == 0, or sa == 0
-       //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
-       //       => colormod breaks in the case GL_SRC_COLOR only
-       //   src == GL_ONE_MINUS_SRC_ALPHA
-       //     s*(1-sa) + d * dst(s, d, sa, da) == d
-       //       => s == 0, or sa == 1
-       //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
-       //       => colormod breaks in the case GL_SRC_COLOR only
-       //   src == GL_DST_ALPHA
-       //     s*da + d * dst(s, d, sa, da) == d
-       //       => s == 0
-       //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
-       //       => colormod is never problematic for these
-
-       switch(src)
-       {
-               case GL_ZERO:
-               case GL_ONE_MINUS_SRC_COLOR:
-               case GL_SRC_ALPHA:
-               case GL_ONE_MINUS_SRC_ALPHA:
-                       if(dst == GL_SRC_COLOR)
-                               return false;
-                       return true;
-               case GL_ONE:
-               case GL_SRC_COLOR:
-               case GL_ONE_MINUS_DST_COLOR:
-               case GL_DST_ALPHA:
-               case GL_ONE_MINUS_DST_ALPHA:
-                       return true;
-               case GL_DST_COLOR:
-                       if(dst == GL_ONE)
-                               return true;
-                       return false;
-               default:
-                       return false;
-       }
-}
-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)
+       // a blendfunc allows fog if:
+       // blend(fog(src), fog(dst)) == fog(blend(src, dst))
+       // this is to prevent unintended side effects from fog
+
+       // these checks are the output of fogeval.pl
+
+       r |= BLENDFUNC_ALLOWS_COLORMOD;
+       if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
+       if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
+       if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
+       if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
+       if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
+       if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
+       if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
+       if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
+       if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
+       if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
+       if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
+       if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
+       if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
+       if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
+       if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
+       if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
+       if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
+       if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
+       if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
+       if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
+       if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
+
+       return r;
+}
+
+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, qboolean notrippy)
 {
        // select a permutation of the lighting shader appropriate to this
        // combination of texture, entity, light source, and fogging, only use the
@@ -5343,95 +2107,90 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
        // fragment shader on features that are not being used
        unsigned int permutation = 0;
        unsigned int mode = 0;
-       qboolean allow_colormod;
+       int blendfuncflags;
        static float dummy_colormod[3] = {1, 1, 1};
        float *colormod = rsurface.colormod;
        float m16f[16];
+       matrix4x4_t tempmatrix;
        r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
+       if (r_trippy.integer && !notrippy)
+               permutation |= SHADERPERMUTATION_TRIPPY;
+       if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
+               permutation |= SHADERPERMUTATION_ALPHAKILL;
+       if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
+               permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
        if (rsurfacepass == RSURFPASS_BACKGROUND)
        {
                // distorted background
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
                {
                        mode = SHADERMODE_WATER;
-                       if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
-                               permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
                        if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
                        {
                                // this is the right thing to do for wateralpha
                                GL_BlendFunc(GL_ONE, GL_ZERO);
-                               allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
+                               blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
                        }
                        else
                        {
                                // this is the right thing to do for entity alpha
                                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-                               allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                               blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                        }
                }
                else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
                {
                        mode = SHADERMODE_REFRACTION;
                        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-                       allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                       blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                }
                else
                {
                        mode = SHADERMODE_GENERIC;
                        permutation |= SHADERPERMUTATION_DIFFUSE;
                        GL_BlendFunc(GL_ONE, GL_ZERO);
-                       allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
+                       blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
                }
-               GL_AlphaTest(false);
+               if (vid.allowalphatocoverage)
+                       GL_AlphaToCoverage(false);
        }
        else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
        {
                if (r_glsl_offsetmapping.integer)
                {
-                       if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING;
-                       else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
-                       else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+                       switch(rsurface.texture->offsetmapping)
                        {
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING;
-                               if (r_glsl_offsetmapping_reliefmapping.integer)
-                                       permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+                       case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
+                       case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
+                       case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
+                       case OFFSETMAPPING_OFF: break;
                        }
                }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
                        permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
-                       permutation |= SHADERPERMUTATION_ALPHAKILL;
                // normalmap (deferred prepass), may use alpha test on diffuse
                mode = SHADERMODE_DEFERREDGEOMETRY;
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
-                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
-               GL_AlphaTest(false);
                GL_BlendFunc(GL_ONE, GL_ZERO);
-               allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
+               blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
+               if (vid.allowalphatocoverage)
+                       GL_AlphaToCoverage(false);
        }
        else if (rsurfacepass == RSURFPASS_RTLIGHT)
        {
                if (r_glsl_offsetmapping.integer)
                {
-                       if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING;
-                       else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
-                       else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+                       switch(rsurface.texture->offsetmapping)
                        {
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING;
-                               if (r_glsl_offsetmapping_reliefmapping.integer)
-                                       permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+                       case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
+                       case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
+                       case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
+                       case OFFSETMAPPING_OFF: break;
                        }
                }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
                        permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
                // light source
                mode = SHADERMODE_LIGHTSOURCE;
-               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
-                       permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
                if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
                        permutation |= SHADERPERMUTATION_CUBEFILTER;
                if (diffusescale > 0)
@@ -5457,23 +2216,21 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                }
                if (rsurface.texture->reflectmasktexture)
                        permutation |= SHADERPERMUTATION_REFLECTCUBE;
-               GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-               allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
+               blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
+               if (vid.allowalphatocoverage)
+                       GL_AlphaToCoverage(false);
        }
        else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
        {
                if (r_glsl_offsetmapping.integer)
                {
-                       if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING;
-                       else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
-                       else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+                       switch(rsurface.texture->offsetmapping)
                        {
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING;
-                               if (r_glsl_offsetmapping_reliefmapping.integer)
-                                       permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+                       case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
+                       case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
+                       case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
+                       case OFFSETMAPPING_OFF: break;
                        }
                }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
@@ -5503,23 +2260,30 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        permutation |= SHADERPERMUTATION_REFLECTION;
                if (rsurface.texture->reflectmasktexture)
                        permutation |= SHADERPERMUTATION_REFLECTCUBE;
-               GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
                GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
-               allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+               blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+               // when using alphatocoverage, we don't need alphakill
+               if (vid.allowalphatocoverage)
+               {
+                       if (r_transparent_alphatocoverage.integer)
+                       {
+                               GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+                               permutation &= ~SHADERPERMUTATION_ALPHAKILL;
+                       }
+                       else
+                               GL_AlphaToCoverage(false);
+               }
        }
        else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
        {
                if (r_glsl_offsetmapping.integer)
                {
-                       if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING;
-                       else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
-                       else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+                       switch(rsurface.texture->offsetmapping)
                        {
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING;
-                               if (r_glsl_offsetmapping_reliefmapping.integer)
-                                       permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+                       case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
+                       case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
+                       case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
+                       case OFFSETMAPPING_OFF: break;
                        }
                }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
@@ -5553,23 +2317,36 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
                if (rsurface.texture->reflectmasktexture)
                        permutation |= SHADERPERMUTATION_REFLECTCUBE;
-               GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+               if (r_shadow_bouncegridtexture)
+               {
+                       permutation |= SHADERPERMUTATION_BOUNCEGRID;
+                       if (r_shadow_bouncegriddirectional)
+                               permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
+               }
                GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
-               allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+               blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+               // when using alphatocoverage, we don't need alphakill
+               if (vid.allowalphatocoverage)
+               {
+                       if (r_transparent_alphatocoverage.integer)
+                       {
+                               GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+                               permutation &= ~SHADERPERMUTATION_ALPHAKILL;
+                       }
+                       else
+                               GL_AlphaToCoverage(false);
+               }
        }
        else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
        {
                if (r_glsl_offsetmapping.integer)
                {
-                       if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING;
-                       else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
-                       else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+                       switch(rsurface.texture->offsetmapping)
                        {
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING;
-                               if (r_glsl_offsetmapping_reliefmapping.integer)
-                                       permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+                       case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
+                       case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
+                       case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
+                       case OFFSETMAPPING_OFF: break;
                        }
                }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
@@ -5600,23 +2377,36 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
                if (rsurface.texture->reflectmasktexture)
                        permutation |= SHADERPERMUTATION_REFLECTCUBE;
-               GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+               if (r_shadow_bouncegridtexture)
+               {
+                       permutation |= SHADERPERMUTATION_BOUNCEGRID;
+                       if (r_shadow_bouncegriddirectional)
+                               permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
+               }
                GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
-               allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+               blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+               // when using alphatocoverage, we don't need alphakill
+               if (vid.allowalphatocoverage)
+               {
+                       if (r_transparent_alphatocoverage.integer)
+                       {
+                               GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+                               permutation &= ~SHADERPERMUTATION_ALPHAKILL;
+                       }
+                       else
+                               GL_AlphaToCoverage(false);
+               }
        }
        else
        {
                if (r_glsl_offsetmapping.integer)
                {
-                       if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING;
-                       else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
-                       else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+                       switch(rsurface.texture->offsetmapping)
                        {
-                               permutation |= SHADERPERMUTATION_OFFSETMAPPING;
-                               if (r_glsl_offsetmapping_reliefmapping.integer)
-                                       permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+                       case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
+                       case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
+                       case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
+                       case OFFSETMAPPING_OFF: break;
                        }
                }
                if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
@@ -5683,12 +2473,32 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        // ordinary vertex coloring (q3bsp)
                        mode = SHADERMODE_VERTEXCOLOR;
                }
-               GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+               if (r_shadow_bouncegridtexture)
+               {
+                       permutation |= SHADERPERMUTATION_BOUNCEGRID;
+                       if (r_shadow_bouncegriddirectional)
+                               permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
+               }
                GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
-               allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+               blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+               // when using alphatocoverage, we don't need alphakill
+               if (vid.allowalphatocoverage)
+               {
+                       if (r_transparent_alphatocoverage.integer)
+                       {
+                               GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+                               permutation &= ~SHADERPERMUTATION_ALPHAKILL;
+                       }
+                       else
+                               GL_AlphaToCoverage(false);
+               }
        }
-       if(!allow_colormod)
+       if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
                colormod = dummy_colormod;
+       if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
+               permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
+       if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
+               permutation |= SHADERPERMUTATION_FOGALPHAHACK;
        switch(vid.renderpath)
        {
        case RENDERPATH_D3D9:
@@ -5752,7 +2562,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                                hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
                        }
                        // additive passes are only darkened by fog, not tinted
-                       if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
+                       if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
                                hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
                        else
                                hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
@@ -5784,7 +2594,12 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
                hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
                hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
-               hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
+               hlslPSSetParameter4f(D3DPSREGISTER_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),
+                               max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
+                       );
                hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
                hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
 
@@ -5837,6 +2652,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES2:
                if (!vid.useinterleavedarrays)
                {
                        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);
@@ -5854,403 +2670,244 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                        R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
                }
                R_SetupShader_SetPermutationGLSL(mode, permutation);
-               if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
+               if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
                if (mode == SHADERMODE_LIGHTSOURCE)
                {
-                       if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
-                       if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
-                       if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
-                       if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
-                       if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
-                       if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
+                       if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
+                       if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
+                       if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
+                       if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
+                       if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
+                       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);
        
                        // additive passes are only darkened by fog, not tinted
                        if (r_glsl_permutation->loc_FogColor >= 0)
-                               qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
-                       if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
+                               qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
+                       if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
                }
                else
                {
                        if (mode == SHADERMODE_FLATCOLOR)
                        {
-                               if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
+                               if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
                        }
                        else if (mode == SHADERMODE_LIGHTDIRECTION)
                        {
-                               if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(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]);
-                               if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
-                               if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(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);
-                               if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(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);
-                               if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
-                               if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(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]);
-                               if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
+                               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]);
+                               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]);
+                               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);
+                               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);
+                               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);
+                               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]);
+                               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]);
                        }
                        else
                        {
-                               if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
-                               if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
-                               if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(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);
-                               if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(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);
-                               if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
+                               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]);
+                               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]);
+                               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);
+                               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);
+                               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);
                        }
                        // additive passes are only darkened by fog, not tinted
                        if (r_glsl_permutation->loc_FogColor >= 0)
                        {
-                               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
-                                       qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
+                               if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
+                                       qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
                                else
-                                       qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
+                                       qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
                        }
-                       if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(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);
-                       if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
-                       if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
-                       if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fARB(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]);
-                       if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fARB(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]);
-                       if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
-                       if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
-                       if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
-                       if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2fARB(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
-               }
-               if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
-               if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
-               if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
-               if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
-               if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(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]);
-
-               if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
-               if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(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));
-               if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
+                       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);
+                       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]);
+                       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]);
+                       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]);
+                       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]);
+                       if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
+                       if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
+                       if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
+                       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]);
+               }
+               if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
+               if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
+               if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
+               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]);
+               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]);
+
+               if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
+               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));
+               if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
                if (r_glsl_permutation->loc_Color_Pants >= 0)
                {
                        if (rsurface.texture->pantstexture)
-                               qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
+                               qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
                        else
-                               qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
+                               qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
                }
                if (r_glsl_permutation->loc_Color_Shirt >= 0)
                {
                        if (rsurface.texture->shirttexture)
-                               qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
+                               qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
                        else
-                               qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
-               }
-               if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
-               if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
-               if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
-               if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
-               if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
-               if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
-               if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
-
-       //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
-       //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
-       //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
-               if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
-               if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
-               if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
-               if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
-               if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
-               if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
-               if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
-               if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
-               if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
-               if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
-               if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
-               if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
-               if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
-               if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
-               if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
-               if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
-               if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
+                               qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
+               }
+               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]);
+               if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
+               if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
+               if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
+               if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(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),
+                               max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
+                       );
+               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]);
+               if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
+               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);}
+               if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
+
+               if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
+               if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
+               if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
+               if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
+               if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
+               if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
+               if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
+               if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
+               if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
+               if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
+               if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
+               if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
+               if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
+               if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
+               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);
+               if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
+               if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
+               if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
+               if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
+               if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
                if (rsurfacepass == RSURFPASS_BACKGROUND)
                {
-                       if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
-                       else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
-                       if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
+                       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);
+                       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);
+                       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);
                }
                else
                {
-                       if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
+                       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);
                }
-//             if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
-//             if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
-               if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
-               if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
+               if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
+               if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
+               if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
+               if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
                if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
                {
-                       if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
+                       if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
                        if (rsurface.rtlight)
                        {
-                               if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
-                               if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
+                               if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
+                               if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
                        }
                }
+               if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
                CHECKGLERROR
                break;
-       case RENDERPATH_CGGL:
-#ifdef SUPPORTCG
-               if (!vid.useinterleavedarrays)
-               {
-                       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);
-                       R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
-                       R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
-                       R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
-                       R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
-                       R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
-                       R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
-                       R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
-               }
-               else
-               {
-                       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);
-                       R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
-               }
-               R_SetupShader_SetPermutationCG(mode, permutation);
-               if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
-               if (mode == SHADERMODE_LIGHTSOURCE)
-               {
-                       if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
-                       if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
-               }
-               else
-               {
-                       if (mode == SHADERMODE_LIGHTDIRECTION)
-                       {
-                               if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
-                       }
-               }
-               if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
-               if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
-               if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
-               if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
-               if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
-               CHECKGLERROR
-
-               if (mode == SHADERMODE_LIGHTSOURCE)
-               {
-                       if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
-                       if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
-                       if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
-                       if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
-                       if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
-
-                       // additive passes are only darkened by fog, not tinted
-                       if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
-                       if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
-               }
-               else
-               {
-                       if (mode == SHADERMODE_FLATCOLOR)
-                       {
-                               if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
-                       }
-                       else if (mode == SHADERMODE_LIGHTDIRECTION)
-                       {
-                               if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_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]);CHECKCGERROR
-                               if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
-                               if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_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);CHECKCGERROR
-                               if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
-                               if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
-                               if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
-                               if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
-                       }
-                       else
-                       {
-                               if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
-                               if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
-                               if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_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);CHECKCGERROR
-                               if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_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);CHECKCGERROR
-                               if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
-                       }
-                       // additive passes are only darkened by fog, not tinted
-                       if (r_cg_permutation->fp_FogColor)
-                       {
-                               if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
-                                       cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
-                               else
-                                       cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
-                               CHECKCGERROR
-                       }
-                       if (r_cg_permutation->fp_DistortScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_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);CHECKCGERROR
-                       if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR
-                       if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR
-                       if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4f(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
-                       if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4f(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
-                       if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
-                       if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
-                       if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
-                       if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
-               }
-               if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
-               if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
-               if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
-               if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));CHECKCGERROR
-               if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
-               if (r_cg_permutation->fp_Color_Pants)
-               {
-                       if (rsurface.texture->pantstexture)
-                               cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
-                       else
-                               cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
-                       CHECKCGERROR
-               }
-               if (r_cg_permutation->fp_Color_Shirt)
-               {
-                       if (rsurface.texture->shirttexture)
-                               cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
-                       else
-                               cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
-                       CHECKCGERROR
-               }
-               if (r_cg_permutation->fp_FogPlane) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
-               if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
-               if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
-               if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
-               if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
-               if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
-               if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
-
-       //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
-       //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
-       //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ReflectCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube    , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
-               if (rsurfacepass == RSURFPASS_BACKGROUND)
-               {
-                       if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);CHECKCGERROR
-                       else if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);CHECKCGERROR
-                       if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
-               }
-               else
-               {
-                       if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
-               }
-               if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
-               if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
-               {
-                       if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
-                       if (rsurface.rtlight)
-                       {
-                               if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
-                               if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
-                       }
-               }
-
-               CHECKGLERROR
-#endif
-               break;
-       case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                break;
        case RENDERPATH_SOFT:
                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);
                R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
                R_SetupShader_SetPermutationSoft(mode, permutation);
-               {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
+               {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
                if (mode == SHADERMODE_LIGHTSOURCE)
                {
-                       {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
-                       DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
-                       DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
-                       DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
-                       DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
-                       DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
+                       {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
+                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
+                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
+                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
+                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
+                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
        
                        // additive passes are only darkened by fog, not tinted
-                       DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
-                       DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
+                       DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
+                       DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
                }
                else
                {
                        if (mode == SHADERMODE_FLATCOLOR)
                        {
-                               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
                        }
                        else if (mode == SHADERMODE_LIGHTDIRECTION)
                        {
-                               DPSOFTRAST_Uniform3fARB(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]);
-                               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
-                               DPSOFTRAST_Uniform3fARB(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);
-                               DPSOFTRAST_Uniform3fARB(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);
-                               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
-                               DPSOFTRAST_Uniform3fARB(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]);
-                               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
+                               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]);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
+                               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);
+                               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);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
+                               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]);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
                        }
                        else
                        {
-                               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
-                               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
-                               DPSOFTRAST_Uniform3fARB(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);
-                               DPSOFTRAST_Uniform3fARB(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);
-                               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
+                               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);
+                               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);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
                        }
                        // additive passes are only darkened by fog, not tinted
-                       if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
-                               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
+                       if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
                        else
-                               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
-                       DPSOFTRAST_Uniform4fARB(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);
-                       DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
-                       DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
-                       DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
-                       DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
-                       DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
-                       DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
-                       DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
-                       DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
-               }
-               {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
-               {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
-               {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
-               DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
-               DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
-
-               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
-               DPSOFTRAST_Uniform1fARB(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));
-               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
+                       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);
+                       DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
+                       DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
+                       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]);
+                       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]);
+                       DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
+                       DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
+                       DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
+                       DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
+               }
+               {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
+               {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
+               {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
+               DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
+               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]);
+
+               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
+               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));
+               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
                if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
                {
                        if (rsurface.texture->pantstexture)
-                               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
                        else
-                               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
                }
                if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
                {
                        if (rsurface.texture->shirttexture)
-                               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
                        else
-                               DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
-               }
-               DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
-               DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
-               DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
-               DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
-               DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
-               DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
-               DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
-
-       //      R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
-       //      R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
-       //      R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
+                               DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
+               }
+               DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
+               DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
+               DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
+               DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
+               DPSOFTRAST_Uniform4f(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),
+                               max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
+                       );
+               DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
+               DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
+
                R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
                R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
                R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
@@ -6267,28 +2924,28 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
                if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
                R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
                R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
-               if (rsurface.rtlight                                      ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
+               if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
                if (rsurfacepass == RSURFPASS_BACKGROUND)
                {
-                       if(DPSOFTRAST_UNIFORM_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
-                       else if(DPSOFTRAST_UNIFORM_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
-                       if(DPSOFTRAST_UNIFORM_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
+                       R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
+                       if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
+                       R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
                }
                else
                {
                        if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
                }
-//             R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
-//             R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
-               R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
-               R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
+//             if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
+//             if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
+               if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
+               if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
                if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
                {
-                       R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
+                       R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
                        if (rsurface.rtlight)
                        {
-                               R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
-                               R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
+                               if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
+                               if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
                        }
                }
                break;
@@ -6320,7 +2977,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
                permutation |= SHADERPERMUTATION_CUBEFILTER;
        if (diffusescale > 0)
                permutation |= SHADERPERMUTATION_DIFFUSE;
-       if (specularscale > 0)
+       if (specularscale > 0 && r_shadow_gloss.integer > 0)
                permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
        if (r_shadow_usingshadowmap2d)
        {
@@ -6335,6 +2992,8 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
                else if (r_shadow_shadowmappcf)
                        permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
        }
+       if (vid.allowalphatocoverage)
+               GL_AlphaToCoverage(false);
        Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
        Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
        Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
@@ -6370,62 +3029,42 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
                Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
                break;
        case RENDERPATH_GL20:
+       case RENDERPATH_GLES2:
                R_SetupShader_SetPermutationGLSL(mode, permutation);
-               if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
-               if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
-               if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
-               if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
-               if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
-               if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
-               if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4fARB(       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]);
-               if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1fARB(       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));
-               if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
-               if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
-
-               if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
-               if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
-               if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
-               if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
-               if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
-               if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
-               break;
-       case RENDERPATH_CGGL:
-#ifdef SUPPORTCG
-               R_SetupShader_SetPermutationCG(mode, permutation);
-               if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
-               if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
-               if (r_cg_permutation->fp_DeferredColor_Ambient    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);CHECKCGERROR
-               if (r_cg_permutation->fp_DeferredColor_Diffuse    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);CHECKCGERROR
-               if (r_cg_permutation->fp_DeferredColor_Specular   ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);CHECKCGERROR
-               if (r_cg_permutation->fp_ShadowMap_TextureScale   ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
-               if (r_cg_permutation->fp_ShadowMap_Parameters     ) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
-               if (r_cg_permutation->fp_SpecularPower            ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
-               if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
-               if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
-
-               if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
-               if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
-#endif
+               if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
+               if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
+               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);
+               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);
+               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);
+               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]);
+               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]);
+               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));
+               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]);
+               if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
+
+               if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
+               if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
+               if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
+               if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
+               if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
+               if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
                break;
-       case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                break;
        case RENDERPATH_SOFT:
                R_SetupShader_SetPermutationGLSL(mode, permutation);
-               DPSOFTRAST_Uniform3fARB(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
-               DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
-               DPSOFTRAST_Uniform3fARB(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
-               DPSOFTRAST_Uniform3fARB(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
-               DPSOFTRAST_Uniform3fARB(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
-               DPSOFTRAST_Uniform2fARB(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
-               DPSOFTRAST_Uniform4fARB(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
-               DPSOFTRAST_Uniform1fARB(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
-               DPSOFTRAST_Uniform2fARB(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
-               DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
+               DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
+               DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
+               DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
+               DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
+               DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
+               DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
+               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]);
+               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));
+               DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
+               DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
 
                R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
                R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
@@ -6627,7 +3266,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        // check for DDS texture file first
        if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
        {
-               basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
+               basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
                if (basepixels == NULL)
                        return NULL;
        }
@@ -6665,7 +3304,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        {
                basepixels_width = image_width;
                basepixels_height = image_height;
-               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);
+               skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
                if (textureflags & TEXF_ALPHA)
                {
                        for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
@@ -6687,16 +3326,16 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
                                        pixels[j+2] = 255;
                                        pixels[j+3] = basepixels[j+3];
                                }
-                               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);
+                               skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
                                Mem_Free(pixels);
                        }
                }
                R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
                //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]);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
-                       R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
+                       R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
-                       R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
+                       R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
        }
 
        if (r_loaddds)
@@ -6718,7 +3357,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
                mymiplevel = savemiplevel;
                if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
                {
-                       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);
+                       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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
                        Mem_Free(pixels);
                        pixels = NULL;
                }
@@ -6726,7 +3365,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
                {
                        pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
                        Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
-                       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);
+                       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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
                        Mem_Free(pixels);
                        Mem_Free(bumppixels);
                }
@@ -6734,60 +3373,60 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
                {
                        pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
                        Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
-                       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);
+                       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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
                        Mem_Free(pixels);
                }
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
-                       R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
+                       R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
        }
 
        // _luma is supported only for tenebrae compatibility
        // _glow is the preferred name
        mymiplevel = savemiplevel;
-       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))))
+       if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
        {
-               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);
+               skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
-                       R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
+                       R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
                Mem_Free(pixels);pixels = NULL;
        }
 
        mymiplevel = savemiplevel;
-       if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
+       if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
        {
-               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);
+               skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
-                       R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
+                       R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
                Mem_Free(pixels);
                pixels = NULL;
        }
 
        mymiplevel = savemiplevel;
-       if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
+       if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
        {
-               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);
+               skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
-                       R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
+                       R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
                Mem_Free(pixels);
                pixels = NULL;
        }
 
        mymiplevel = savemiplevel;
-       if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
+       if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
        {
-               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);
+               skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
-                       R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
+                       R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
                Mem_Free(pixels);
                pixels = NULL;
        }
 
        mymiplevel = savemiplevel;
-       if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
+       if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
        {
-               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);
+               skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
                if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
-                       R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
+                       R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
                Mem_Free(pixels);
                pixels = NULL;
        }
@@ -6799,7 +3438,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
 }
 
 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
-skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
+skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
 {
        int i;
        unsigned char *temp1, *temp2;
@@ -6840,7 +3479,7 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co
                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);
                Mem_Free(temp1);
        }
-       skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
+       skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
        if (textureflags & TEXF_ALPHA)
        {
                for (i = 3;i < width * height * 4;i += 4)
@@ -6967,20 +3606,20 @@ static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboo
        if (skinframe->qgenerateglow)
        {
                skinframe->qgenerateglow = false;
-               skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
+               skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
        }
 
        if (colormapped)
        {
                skinframe->qgeneratebase = false;
-               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);
-               skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
-               skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
+               skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
+               skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
+               skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
        }
        else
        {
                skinframe->qgeneratemerged = false;
-               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);
+               skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
        }
 
        if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
@@ -7127,7 +3766,7 @@ rtexture_t *R_LoadCubemap(const char *basename)
                        // generate an image name based on the base and and suffix
                        dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
                        // load it
-                       if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
+                       if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
                        {
                                // an image loaded, make sure width and height are equal
                                if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
@@ -7156,7 +3795,7 @@ rtexture_t *R_LoadCubemap(const char *basename)
                if (developer_loading.integer)
                        Con_Printf("loading cubemap \"%s\"\n", basename);
 
-               cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
+               cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
                Mem_Free(cubemappixels);
        }
        else
@@ -7178,14 +3817,36 @@ rtexture_t *R_GetCubemap(const char *basename)
 {
        int i;
        for (i = 0;i < r_texture_numcubemaps;i++)
-               if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
-                       return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
-       if (i >= MAX_CUBEMAPS)
+               if (r_texture_cubemaps[i] != NULL)
+                       if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
+                               return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
+       if (i >= MAX_CUBEMAPS || !r_main_mempool)
                return r_texture_whitecube;
        r_texture_numcubemaps++;
-       strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
-       r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
-       return r_texture_cubemaps[i].texture;
+       r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
+       strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
+       r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
+       return r_texture_cubemaps[i]->texture;
+}
+
+void R_FreeCubemap(const char *basename)
+{
+       int i;
+
+       for (i = 0;i < r_texture_numcubemaps;i++)
+       {
+               if (r_texture_cubemaps[i] != NULL)
+               {
+                       if (r_texture_cubemaps[i]->texture)
+                       {
+                               if (developer_loading.integer)
+                                       Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
+                               R_FreeTexture(r_texture_cubemaps[i]->texture);
+                               Mem_Free(r_texture_cubemaps[i]);
+                               r_texture_cubemaps[i] = NULL;
+                       }
+               }
+       }
 }
 
 void R_FreeCubemaps(void)
@@ -7194,9 +3855,13 @@ void R_FreeCubemaps(void)
        for (i = 0;i < r_texture_numcubemaps;i++)
        {
                if (developer_loading.integer)
-                       Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
-               if (r_texture_cubemaps[i].texture)
-                       R_FreeTexture(r_texture_cubemaps[i].texture);
+                       Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
+               if (r_texture_cubemaps[i] != NULL)
+               {
+                       if (r_texture_cubemaps[i]->texture)
+                               R_FreeTexture(r_texture_cubemaps[i]->texture);
+                       Mem_Free(r_texture_cubemaps[i]);
+               }
        }
        r_texture_numcubemaps = 0;
 }
@@ -7267,17 +3932,17 @@ void gl_main_start(void)
        r_texture_gammaramps = NULL;
        r_texture_numcubemaps = 0;
 
-       r_loaddds = r_texture_dds_load.integer;
+       r_loaddds = r_texture_dds_load.integer != 0;
        r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
 
        switch(vid.renderpath)
        {
        case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                Cvar_SetValueQuick(&r_textureunits, vid.texunits);
                Cvar_SetValueQuick(&gl_combine, 1);
                Cvar_SetValueQuick(&r_glsl, 1);
@@ -7286,6 +3951,7 @@ void gl_main_start(void)
                r_loadfog = false;
                break;
        case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                Cvar_SetValueQuick(&r_textureunits, vid.texunits);
                Cvar_SetValueQuick(&gl_combine, 1);
                Cvar_SetValueQuick(&r_glsl, 0);
@@ -7313,6 +3979,9 @@ void gl_main_start(void)
        r_qwskincache = NULL;
        r_qwskincache_size = 0;
 
+       // due to caching of texture_t references, the collision cache must be reset
+       Collision_Cache_Reset(true);
+
        // set up r_skinframe loading system for textures
        memset(&r_skinframe, 0, sizeof(r_skinframe));
        r_skinframe.loadsequence = 1;
@@ -7336,20 +4005,17 @@ void gl_main_start(void)
        memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
        Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
        glslshaderstring = NULL;
-#ifdef SUPPORTCG
-       r_cg_permutation = NULL;
-       memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
-       Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
-       cgshaderstring = NULL;
-#endif
 #ifdef SUPPORTD3D
        r_hlsl_permutation = NULL;
        memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
        Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
-       hlslshaderstring = NULL;
 #endif
+       hlslshaderstring = NULL;
        memset(&r_svbsp, 0, sizeof (r_svbsp));
 
+       memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
+       r_texture_numcubemaps = 0;
+
        r_refdef.fogmasktable_density = 0;
 }
 
@@ -7365,7 +4031,8 @@ void gl_main_shutdown(void)
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
+       case RENDERPATH_GLES1:
+       case RENDERPATH_GLES2:
                if (r_maxqueries)
                        qglDeleteQueriesARB(r_maxqueries, r_queries);
                break;
@@ -7417,18 +4084,12 @@ void gl_main_shutdown(void)
        memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
        Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
        glslshaderstring = NULL;
-#ifdef SUPPORTCG
-       r_cg_permutation = NULL;
-       memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
-       Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
-       cgshaderstring = NULL;
-#endif
 #ifdef SUPPORTD3D
        r_hlsl_permutation = NULL;
        memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
        Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
-       hlslshaderstring = NULL;
 #endif
+       hlslshaderstring = NULL;
 }
 
 extern void CL_ParseEntityLump(char *entitystring);
@@ -7492,6 +4153,10 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_farclip_base);
        Cvar_RegisterVariable(&r_farclip_world);
        Cvar_RegisterVariable(&r_nearclip);
+       Cvar_RegisterVariable(&r_deformvertexes);
+       Cvar_RegisterVariable(&r_transparent);
+       Cvar_RegisterVariable(&r_transparent_alphatocoverage);
+       Cvar_RegisterVariable(&r_showoverdraw);
        Cvar_RegisterVariable(&r_showbboxes);
        Cvar_RegisterVariable(&r_showsurfaces);
        Cvar_RegisterVariable(&r_showtris);
@@ -7534,21 +4199,30 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
        Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
        Cvar_RegisterVariable(&r_fog_exp2);
+       Cvar_RegisterVariable(&r_fog_clear);
        Cvar_RegisterVariable(&r_drawfog);
        Cvar_RegisterVariable(&r_transparentdepthmasking);
+       Cvar_RegisterVariable(&r_transparent_sortmaxdist);
+       Cvar_RegisterVariable(&r_transparent_sortarraysize);
        Cvar_RegisterVariable(&r_texture_dds_load);
        Cvar_RegisterVariable(&r_texture_dds_save);
-       Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
-       Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
-       Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
-       Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
-       Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
        Cvar_RegisterVariable(&r_textureunits);
        Cvar_RegisterVariable(&gl_combine);
+       Cvar_RegisterVariable(&r_viewfbo);
+       Cvar_RegisterVariable(&r_viewscale);
+       Cvar_RegisterVariable(&r_viewscale_fpsscaling);
+       Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
+       Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
+       Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
+       Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
+       Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
        Cvar_RegisterVariable(&r_glsl);
        Cvar_RegisterVariable(&r_glsl_deluxemapping);
        Cvar_RegisterVariable(&r_glsl_offsetmapping);
+       Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
        Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
+       Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
+       Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
        Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
        Cvar_RegisterVariable(&r_glsl_postprocess);
        Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
@@ -7566,6 +4240,8 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_water_refractdistort);
        Cvar_RegisterVariable(&r_water_reflectdistort);
        Cvar_RegisterVariable(&r_water_scissormode);
+       Cvar_RegisterVariable(&r_water_lowquality);
+
        Cvar_RegisterVariable(&r_lerpsprites);
        Cvar_RegisterVariable(&r_lerpmodels);
        Cvar_RegisterVariable(&r_lerplightstyles);
@@ -7581,25 +4257,23 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_hdr_scenebrightness);
        Cvar_RegisterVariable(&r_hdr_glowintensity);
        Cvar_RegisterVariable(&r_hdr_range);
+       Cvar_RegisterVariable(&r_hdr_irisadaptation);
+       Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
+       Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
+       Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
+       Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
+       Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
        Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
        Cvar_RegisterVariable(&developer_texturelogging);
        Cvar_RegisterVariable(&gl_lightmaps);
        Cvar_RegisterVariable(&r_test);
        Cvar_RegisterVariable(&r_glsl_saturation);
        Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
+       Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
        Cvar_RegisterVariable(&r_framedatasize);
        if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
                Cvar_SetValue("r_fullbrights", 0);
        R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
-
-       Cvar_RegisterVariable(&r_track_sprites);
-       Cvar_RegisterVariable(&r_track_sprites_flags);
-       Cvar_RegisterVariable(&r_track_sprites_scalew);
-       Cvar_RegisterVariable(&r_track_sprites_scaleh);
-       Cvar_RegisterVariable(&r_overheadsprites_perspective);
-       Cvar_RegisterVariable(&r_overheadsprites_pushback);
-       Cvar_RegisterVariable(&r_overheadsprites_scalex);
-       Cvar_RegisterVariable(&r_overheadsprites_scaley);
 }
 
 extern void R_Textures_Init(void);
@@ -7670,6 +4344,8 @@ int R_CullBox(const vec3_t mins, const vec3_t maxs)
 {
        int i;
        mplane_t *p;
+       if (r_trippy.integer)
+               return false;
        for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
        {
                // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
@@ -7720,6 +4396,8 @@ int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, c
 {
        int i;
        const mplane_t *p;
+       if (r_trippy.integer)
+               return false;
        for (i = 0;i < numplanes;i++)
        {
                p = planes + i;
@@ -7965,7 +4643,7 @@ qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qbool
        else
        {
                // see if this ent is worth caching
-               if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
+               if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
                        return false;
                // get some memory for this entity and generate mesh data
                numvertices = model->surfmesh.num_vertices;
@@ -7992,13 +4670,14 @@ void R_AnimCache_CacheVisibleEntities(void)
        switch(vid.renderpath)
        {
        case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
+       case RENDERPATH_GLES2:
                break;
-       case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                wanttangents = false;
                break;
        case RENDERPATH_SOFT:
@@ -8018,6 +4697,8 @@ void R_AnimCache_CacheVisibleEntities(void)
 
 //==================================================================================
 
+extern cvar_t r_overheadsprites_pushback;
+
 static void R_View_UpdateEntityLighting (void)
 {
        int i;
@@ -8048,7 +4729,7 @@ static void R_View_UpdateEntityLighting (void)
                VectorClear(ent->modellight_ambient);
                VectorClear(ent->modellight_diffuse);
                VectorClear(tempdiffusenormal);
-               if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
+               if (ent->flags & RENDER_LIGHT)
                {
                        vec3_t org;
                        Matrix4x4_OriginFromMatrix(&ent->matrix, org);
@@ -8059,10 +4740,10 @@ static void R_View_UpdateEntityLighting (void)
                        {
                                if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
                                        org[2] = org[2] + r_overheadsprites_pushback.value;
-                               R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
+                               R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
                        }
                        else
-                               r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
+                               R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
 
                        if(ent->flags & RENDER_EQUALIZE)
                        {
@@ -8190,24 +4871,6 @@ static void R_View_UpdateEntityVisible (void)
                        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))
                                r_refdef.viewcache.entityvisible[i] = true;
                }
-               if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
-                       // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
-               {
-                       for (i = 0;i < r_refdef.scene.numentities;i++)
-                       {
-                               ent = r_refdef.scene.entities[i];
-                               if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
-                               {
-                                       samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
-                                       if (samples < 0)
-                                               continue; // temp entities do pvs only
-                                       if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
-                                               ent->last_trace_visibility = realtime;
-                                       if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
-                                               r_refdef.viewcache.entityvisible[i] = 0;
-                               }
-                       }
-               }
        }
        else
        {
@@ -8218,6 +4881,26 @@ static void R_View_UpdateEntityVisible (void)
                        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));
                }
        }
+       if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
+               // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
+       {
+               for (i = 0;i < r_refdef.scene.numentities;i++)
+               {
+                       if (!r_refdef.viewcache.entityvisible[i])
+                               continue;
+                       ent = r_refdef.scene.entities[i];
+                       if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
+                       {
+                               samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
+                               if (samples < 0)
+                                       continue; // temp entities do pvs only
+                               if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
+                                       ent->last_trace_visibility = realtime;
+                               if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
+                                       r_refdef.viewcache.entityvisible[i] = 0;
+                       }
+               }
+       }
 }
 
 /// only used if skyrendermasked, and normally returns false
@@ -8252,6 +4935,17 @@ static void R_DrawModels(void)
                        continue;
                ent = r_refdef.scene.entities[i];
                r_refdef.stats.entities++;
+               /*
+               if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
+               {
+                       vec3_t f, l, u, o;
+                       Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
+                       Con_Printf("R_DrawModels\n");
+                       Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
+                       Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
+                       Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
+               }
+               */
                if (ent->model && ent->model->Draw != NULL)
                        ent->model->Draw(ent);
                else
@@ -8304,6 +4998,35 @@ static void R_DrawModelsAddWaterPlanes(void)
        }
 }
 
+void R_HDR_UpdateIrisAdaptation(const vec3_t point)
+{
+       if (r_hdr_irisadaptation.integer)
+       {
+               vec3_t ambient;
+               vec3_t diffuse;
+               vec3_t diffusenormal;
+               vec_t brightness;
+               vec_t goal;
+               vec_t adjust;
+               vec_t current;
+               R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
+               brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
+               brightness = max(0.0000001f, brightness);
+               goal = r_hdr_irisadaptation_multiplier.value / brightness;
+               goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
+               adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
+               current = r_hdr_irisadaptation_value.value;
+               if (current < goal)
+                       current = min(current + adjust, goal);
+               else if (current > goal)
+                       current = max(current - adjust, goal);
+               if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
+                       Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
+       }
+       else if (r_hdr_irisadaptation_value.value != 1.0f)
+               Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
+}
+
 static void R_View_SetFrustum(const int *scissor)
 {
        int i;
@@ -8322,15 +5045,16 @@ static void R_View_SetFrustum(const int *scissor)
                        case RENDERPATH_D3D9:
                        case RENDERPATH_D3D10:
                        case RENDERPATH_D3D11:
-                       case RENDERPATH_SOFT:
                                // non-flipped y coordinates
                                fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
                                fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
                                break;
+                       case RENDERPATH_SOFT:
                        case RENDERPATH_GL11:
                        case RENDERPATH_GL13:
                        case RENDERPATH_GL20:
-                       case RENDERPATH_CGGL:
+                       case RENDERPATH_GLES1:
+                       case RENDERPATH_GLES2:
                                // non-flipped y coordinates
                                fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
                                fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
@@ -8524,10 +5248,29 @@ void R_View_Update(void)
        R_View_UpdateEntityLighting();
 }
 
+float viewscalefpsadjusted = 1.0f;
+
+void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
+{
+       float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
+       scale = bound(0.03125f, scale, 1.0f);
+       *outwidth = (int)ceil(width * scale);
+       *outheight = (int)ceil(height * scale);
+}
+
+void R_Mesh_SetMainRenderTargets(void)
+{
+       if (r_bloomstate.fbo_framebuffer)
+               R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
+       else
+               R_Mesh_ResetRenderTargets();
+}
+
 void R_SetupView(qboolean allowwaterclippingplane)
 {
        const float *customclipplane = NULL;
        float plane[4];
+       int scaledwidth, scaledheight;
        if (r_refdef.view.useclipplane && allowwaterclippingplane)
        {
                // LordHavoc: couldn't figure out how to make this approach the
@@ -8538,17 +5281,29 @@ void R_SetupView(qboolean allowwaterclippingplane)
                plane[0] = r_refdef.view.clipplane.normal[0];
                plane[1] = r_refdef.view.clipplane.normal[1];
                plane[2] = r_refdef.view.clipplane.normal[2];
-               plane[3] = dist;
-               customclipplane = plane;
+               plane[3] = -dist;
+               if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
        }
 
+       R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
        if (!r_refdef.view.useperspective)
-               R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
+               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);
        else if (vid.stencil && r_useinfinitefarclip.integer)
-               R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
+               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);
        else
-               R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
+               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);
+       R_Mesh_SetMainRenderTargets();
        R_SetViewport(&r_refdef.view.viewport);
+       if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
+       {
+               matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
+               float screenplane[4];
+               Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
+               Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
+               Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
+               Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
+               DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
+       }
 }
 
 void R_EntityMatrix(const matrix4x4_t *matrix)
@@ -8576,26 +5331,19 @@ void R_EntityMatrix(const matrix4x4_t *matrix)
                case RENDERPATH_D3D11:
                        Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
                        break;
-               case RENDERPATH_GL20:
-                       if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
-                       if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
-                       qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
-                       break;
-               case RENDERPATH_CGGL:
-#ifdef SUPPORTCG
-                       CHECKCGERROR
-                       if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
-                       if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
-                       qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
-#endif
-                       break;
-               case RENDERPATH_GL13:
                case RENDERPATH_GL11:
+               case RENDERPATH_GL13:
+               case RENDERPATH_GLES1:
                        qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
                        break;
                case RENDERPATH_SOFT:
-                       DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
-                       DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
+                       DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
+                       DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
+                       break;
+               case RENDERPATH_GL20:
+               case RENDERPATH_GLES2:
+                       if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
+                       if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
                        break;
                }
        }
@@ -8608,12 +5356,12 @@ void R_ResetViewRendering2D(void)
 
        // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
        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);
+       R_Mesh_ResetRenderTargets();
        R_SetViewport(&viewport);
        GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
        GL_Color(1, 1, 1, 1);
        GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
        GL_BlendFunc(GL_ONE, GL_ZERO);
-       GL_AlphaTest(false);
        GL_ScissorTest(false);
        GL_DepthMask(false);
        GL_DepthRange(0, 1);
@@ -8628,7 +5376,8 @@ void R_ResetViewRendering2D(void)
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
+       case RENDERPATH_GLES1:
+       case RENDERPATH_GLES2:
                qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
                break;
        case RENDERPATH_D3D9:
@@ -8649,7 +5398,6 @@ void R_ResetViewRendering3D(void)
        GL_Color(1, 1, 1, 1);
        GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
        GL_BlendFunc(GL_ONE, GL_ZERO);
-       GL_AlphaTest(false);
        GL_ScissorTest(true);
        GL_DepthMask(true);
        GL_DepthRange(0, 1);
@@ -8664,7 +5412,8 @@ void R_ResetViewRendering3D(void)
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
+       case RENDERPATH_GLES1:
+       case RENDERPATH_GLES2:
                qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
                break;
        case RENDERPATH_D3D9:
@@ -8707,21 +5456,21 @@ static void R_Water_StartFrame(void)
        switch(vid.renderpath)
        {
        case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                break;
-       case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                return;
        }
 
        // set waterwidth and waterheight to the water resolution that will be
        // used (often less than the screen resolution for faster rendering)
-       waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
-       waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
+       R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
 
        // calculate desired texture sizes
        // can't use water if the card does not support the texture size
@@ -8767,17 +5516,20 @@ static void R_Water_StartFrame(void)
 
        if (r_waterstate.texturewidth)
        {
+               int scaledwidth, scaledheight;
+
                r_waterstate.enabled = true;
 
                // when doing a reduced render (HDR) we want to use a smaller area
                r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
                r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
+               R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
 
                // set up variables that will be used in shader setup
-               r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
-               r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
-               r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
-               r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
+               r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
+               r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
+               r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
+               r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
        }
 
        r_waterstate.maxwaterplanes = MAX_WATERPLANES;
@@ -8868,17 +5620,44 @@ void R_Water_AddWaterPlane(msurface_t *surface, int entno)
        }
 }
 
+extern cvar_t r_drawparticles;
+extern cvar_t r_drawdecals;
+
 static void R_Water_ProcessPlanes(void)
 {
        int myscissor[4];
        r_refdef_view_t originalview;
        r_refdef_view_t myview;
-       int planeindex;
+       int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
        r_waterstate_waterplane_t *p;
        vec3_t visorigin;
 
        originalview = r_refdef.view;
 
+       // lowquality hack, temporarily shut down some cvars and restore afterwards
+       qualityreduction = r_water_lowquality.integer;
+       if (qualityreduction > 0)
+       {
+               if (qualityreduction >= 1)
+               {
+                       old_r_shadows = r_shadows.integer;
+                       old_r_worldrtlight = r_shadow_realtime_world.integer;
+                       old_r_dlight = r_shadow_realtime_dlight.integer;
+                       Cvar_SetValueQuick(&r_shadows, 0);
+                       Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
+                       Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
+               }
+               if (qualityreduction >= 2)
+               {
+                       old_r_dynamic = r_dynamic.integer;
+                       old_r_particles = r_drawparticles.integer;
+                       old_r_decals = r_drawdecals.integer;
+                       Cvar_SetValueQuick(&r_dynamic, 0);
+                       Cvar_SetValueQuick(&r_drawparticles, 0);
+                       Cvar_SetValueQuick(&r_drawdecals, 0);
+               }
+       }
+
        // make sure enough textures are allocated
        for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
        {
@@ -8931,7 +5710,6 @@ static void R_Water_ProcessPlanes(void)
                        // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
                        Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
                        r_refdef.view.clipplane = p->plane;
-
                        // reverse the cullface settings for this render
                        r_refdef.view.cullface_front = GL_FRONT;
                        r_refdef.view.cullface_back = GL_BACK;
@@ -9052,35 +5830,74 @@ static void R_Water_ProcessPlanes(void)
                }
 
        }
+       if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
        r_waterstate.renderingscene = false;
        r_refdef.view = originalview;
        R_ResetViewRendering3D();
        R_ClearScreen(r_refdef.fogenabled);
        R_View_Update();
-       return;
+       goto finish;
 error:
        r_refdef.view = originalview;
        r_waterstate.renderingscene = false;
        Cvar_SetValueQuick(&r_water, 0);
        Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
-       return;
+finish:
+       // lowquality hack, restore cvars
+       if (qualityreduction > 0)
+       {
+               if (qualityreduction >= 1)
+               {
+                       Cvar_SetValueQuick(&r_shadows, old_r_shadows);
+                       Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
+                       Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
+               }
+               if (qualityreduction >= 2)
+               {
+                       Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
+                       Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
+                       Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
+               }
+       }
 }
 
 void R_Bloom_StartFrame(void)
 {
        int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
+       int viewwidth, viewheight;
+       textype_t textype;
+
+       if (r_viewscale_fpsscaling.integer)
+       {
+               double actualframetime;
+               double targetframetime;
+               double adjust;
+               actualframetime = r_refdef.lastdrawscreentime;
+               targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
+               adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
+               adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
+               if (r_viewscale_fpsscaling_stepsize.value > 0)
+                       adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
+               viewscalefpsadjusted += adjust;
+               viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
+       }
+       else
+               viewscalefpsadjusted = 1.0f;
+
+       R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
 
        switch(vid.renderpath)
        {
        case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                break;
-       case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                return;
        }
 
@@ -9095,8 +5912,8 @@ void R_Bloom_StartFrame(void)
        // calculate desired texture sizes
        if (vid.support.arb_texture_non_power_of_two)
        {
-               screentexturewidth = r_refdef.view.width;
-               screentextureheight = r_refdef.view.height;
+               screentexturewidth = vid.width;
+               screentextureheight = vid.height;
                bloomtexturewidth = r_bloomstate.bloomwidth;
                bloomtextureheight = r_bloomstate.bloomheight;
        }
@@ -9116,31 +5933,83 @@ void R_Bloom_StartFrame(void)
                Cvar_SetValueQuick(&r_damageblur, 0);
        }
 
-       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)))
+       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 && !r_viewscale_fpsscaling.integer)
                screentexturewidth = screentextureheight = 0;
        if (!r_hdr.integer && !r_bloom.integer)
                bloomtexturewidth = bloomtextureheight = 0;
 
+       textype = TEXTYPE_COLORBUFFER;
+       switch (vid.renderpath)
+       {
+       case RENDERPATH_GL20:
+       case RENDERPATH_GLES2:
+               if (vid.support.ext_framebuffer_object)
+               {
+                       if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
+                       if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
+               }
+               break;
+       case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
+       case RENDERPATH_D3D9:
+       case RENDERPATH_D3D10:
+       case RENDERPATH_D3D11:
+       case RENDERPATH_SOFT:
+               break;
+       }
+
        // allocate textures as needed
-       if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
+       if (r_bloomstate.screentexturewidth != screentexturewidth
+        || r_bloomstate.screentextureheight != screentextureheight
+        || r_bloomstate.bloomtexturewidth != bloomtexturewidth
+        || r_bloomstate.bloomtextureheight != bloomtextureheight
+        || r_bloomstate.texturetype != textype
+        || r_bloomstate.viewfbo != r_viewfbo.integer)
        {
+               if (r_bloomstate.texture_bloom)
+                       R_FreeTexture(r_bloomstate.texture_bloom);
+               r_bloomstate.texture_bloom = NULL;
                if (r_bloomstate.texture_screen)
                        R_FreeTexture(r_bloomstate.texture_screen);
                r_bloomstate.texture_screen = NULL;
+               if (r_bloomstate.fbo_framebuffer)
+                       R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
+               r_bloomstate.fbo_framebuffer = 0;
+               if (r_bloomstate.texture_framebuffercolor)
+                       R_FreeTexture(r_bloomstate.texture_framebuffercolor);
+               r_bloomstate.texture_framebuffercolor = NULL;
+               if (r_bloomstate.texture_framebufferdepth)
+                       R_FreeTexture(r_bloomstate.texture_framebufferdepth);
+               r_bloomstate.texture_framebufferdepth = NULL;
                r_bloomstate.screentexturewidth = screentexturewidth;
                r_bloomstate.screentextureheight = screentextureheight;
                if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
-                       r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
-       }
-       if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
-       {
-               if (r_bloomstate.texture_bloom)
-                       R_FreeTexture(r_bloomstate.texture_bloom);
-               r_bloomstate.texture_bloom = NULL;
+                       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);
+               if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
+               {
+                       // FIXME: choose depth bits based on a cvar
+                       r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
+                       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);
+                       r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
+                       R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
+                       // render depth into one texture and normalmap into the other
+                       if (qglDrawBuffer)
+                       {
+                               int status;
+                               qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
+                               qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
+                               status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
+                               if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+                                       Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
+                       }
+               }
                r_bloomstate.bloomtexturewidth = bloomtexturewidth;
                r_bloomstate.bloomtextureheight = bloomtextureheight;
                if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
-                       r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
+                       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);
+               r_bloomstate.viewfbo = r_viewfbo.integer;
+               r_bloomstate.texturetype = textype;
        }
 
        // when doing a reduced render (HDR) we want to use a smaller area
@@ -9153,10 +6022,10 @@ void R_Bloom_StartFrame(void)
        // set up a texcoord array for the full resolution screen image
        // (we have to keep this around to copy back during final render)
        r_bloomstate.screentexcoord2f[0] = 0;
-       r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
-       r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
-       r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
-       r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
+       r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
+       r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
+       r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
+       r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
        r_bloomstate.screentexcoord2f[5] = 0;
        r_bloomstate.screentexcoord2f[6] = 0;
        r_bloomstate.screentexcoord2f[7] = 0;
@@ -9177,8 +6046,9 @@ void R_Bloom_StartFrame(void)
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES1:
+       case RENDERPATH_GLES2:
                break;
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
@@ -9196,13 +6066,16 @@ void R_Bloom_StartFrame(void)
                break;
        }
 
-       if (r_hdr.integer || r_bloom.integer)
+       if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
        {
                r_bloomstate.enabled = true;
-               r_bloomstate.hdr = r_hdr.integer != 0;
+               r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
        }
 
        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);
+
+       if (r_bloomstate.fbo_framebuffer)
+               r_refdef.view.clear = true;
 }
 
 void R_Bloom_CopyBloomTexture(float colorscale)
@@ -9211,6 +6084,7 @@ void R_Bloom_CopyBloomTexture(float colorscale)
 
        // scale down screen texture to the bloom texture size
        CHECKGLERROR
+       R_Mesh_SetMainRenderTargets();
        R_SetViewport(&r_bloomstate.viewport);
        GL_BlendFunc(GL_ONE, GL_ZERO);
        GL_Color(colorscale, colorscale, colorscale, 1);
@@ -9220,7 +6094,8 @@ void R_Bloom_CopyBloomTexture(float colorscale)
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
        case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
+       case RENDERPATH_GLES1:
+       case RENDERPATH_GLES2:
        case RENDERPATH_SOFT:
                R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
                break;
@@ -9231,7 +6106,7 @@ void R_Bloom_CopyBloomTexture(float colorscale)
                break;
        }
        // TODO: do boxfilter scale-down in shader?
-       R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
+       R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
        R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
        r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
 
@@ -9267,7 +6142,7 @@ void R_Bloom_MakeTexture(void)
                GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
                GL_Color(r,r,r,1);
                R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
-               R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
+               R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
                R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
                r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
 
@@ -9278,12 +6153,12 @@ void R_Bloom_MakeTexture(void)
 
        range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
        brighten = r_bloom_brighten.value;
-       if (r_hdr.integer)
+       if (r_bloomstate.hdr)
                brighten *= r_hdr_range.value;
        brighten = sqrt(brighten);
        if(range >= 1)
                brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
-       R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
+       R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
 
        for (dir = 0;dir < 2;dir++)
        {
@@ -9331,7 +6206,7 @@ void R_HDR_RenderBloomTexture(void)
 {
        int oldwidth, oldheight;
        float oldcolorscale;
-       int oldwaterstate;
+       qboolean oldwaterstate;
 
        oldwaterstate = r_waterstate.enabled;
        oldcolorscale = r_refdef.view.colorscale;
@@ -9395,11 +6270,11 @@ static void R_BlendView(void)
        switch (vid.renderpath)
        {
        case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                permutation =
                          (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
                        | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
@@ -9413,6 +6288,7 @@ static void R_BlendView(void)
                        if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
 
                        R_ResetViewRendering2D();
+                       R_Mesh_SetMainRenderTargets();
 
                        if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
                        {
@@ -9452,7 +6328,8 @@ static void R_BlendView(void)
                                        case RENDERPATH_GL11:
                                        case RENDERPATH_GL13:
                                        case RENDERPATH_GL20:
-                                       case RENDERPATH_CGGL:
+                                       case RENDERPATH_GLES1:
+                                       case RENDERPATH_GLES2:
                                        case RENDERPATH_SOFT:
                                                R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
                                                break;
@@ -9462,7 +6339,7 @@ static void R_BlendView(void)
                                                R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
                                                break;
                                        }
-                                       R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
+                                       R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
                                        R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
                                        r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
                                }
@@ -9481,7 +6358,7 @@ static void R_BlendView(void)
                                R_ResetViewRendering2D();
                                GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
                                R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
-                               R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+                               R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
                                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                                R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
                        }
@@ -9517,38 +6394,21 @@ static void R_BlendView(void)
                switch(vid.renderpath)
                {
                case RENDERPATH_GL20:
+               case RENDERPATH_GLES2:
                        R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
                        R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
-                       if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
-                       if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
-                       if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
-                       if (r_glsl_permutation->loc_ViewTintColor      >= 0) qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
-                       if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
-                       if (r_glsl_permutation->loc_UserVec1           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
-                       if (r_glsl_permutation->loc_UserVec2           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
-                       if (r_glsl_permutation->loc_UserVec3           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
-                       if (r_glsl_permutation->loc_UserVec4           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
-                       if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
-                       if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
-                       if (r_glsl_permutation->loc_BloomColorSubtract    >= 0) qglUniform4fARB(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
-                       break;
-               case RENDERPATH_CGGL:
-#ifdef SUPPORTCG
-                       R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
-                       R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
-                       if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
-                       if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
-                       if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
-                       if (r_cg_permutation->fp_ViewTintColor     ) cgGLSetParameter4f(     r_cg_permutation->fp_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);CHECKCGERROR
-                       if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
-                       if (r_cg_permutation->fp_UserVec1          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);CHECKCGERROR
-                       if (r_cg_permutation->fp_UserVec2          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);CHECKCGERROR
-                       if (r_cg_permutation->fp_UserVec3          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);CHECKCGERROR
-                       if (r_cg_permutation->fp_UserVec4          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);CHECKCGERROR
-                       if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
-                       if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
-                       if (r_cg_permutation->fp_BloomColorSubtract   ) cgGLSetParameter4f(r_cg_permutation->fp_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
-#endif
+                       if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
+                       if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
+                       if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
+                       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]);
+                       if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
+                       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]);
+                       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]);
+                       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]);
+                       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]);
+                       if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
+                       if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
+                       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);
                        break;
                case RENDERPATH_D3D9:
 #ifdef SUPPORTD3D
@@ -9581,31 +6441,32 @@ static void R_BlendView(void)
                        R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
                        R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
                        R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
-                       DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
-                       DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
-                       DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
-                       DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
-                       DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
-                       DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
-                       DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
-                       DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
-                       DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
+                       DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
+                       DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
+                       DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
+                       DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
+                       DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
+                       DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
+                       DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
+                       DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
+                       DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
                        break;
                default:
                        break;
                }
                R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
-               r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
+               r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
                break;
-       case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
                {
                        // apply a color tint to the whole view
                        R_ResetViewRendering2D();
                        GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
                        R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
-                       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+                       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
                        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                        R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
                }
@@ -9740,11 +6601,11 @@ void R_UpdateVariables(void)
        switch(vid.renderpath)
        {
        case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                if(v_glslgamma.integer && !vid_gammatables_trivial)
                {
                        if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
@@ -9767,7 +6628,7 @@ void R_UpdateVariables(void)
                                }
                                if (r_texture_gammaramps)
                                {
-                                       R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
+                                       R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
                                }
                                else
                                {
@@ -9780,8 +6641,9 @@ void R_UpdateVariables(void)
                        // remove GLSL gamma texture
                }
                break;
-       case RENDERPATH_GL13:
        case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                break;
        }
 }
@@ -9823,9 +6685,13 @@ r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
 R_RenderView
 ================
 */
+int dpsoftrast_test;
 void R_RenderView(void)
 {
        matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
+
+       dpsoftrast_test = r_test.integer;
+
        if (r_timereport_active)
                R_TimeReport("start");
        r_textureframe++; // used only by R_GetCurrentTexture
@@ -9872,7 +6738,7 @@ void R_RenderView(void)
                return; //Host_Error ("R_RenderView: NULL worldmodel");
        }
 
-       r_refdef.view.colorscale = r_hdr_scenebrightness.value;
+       r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
 
        R_RenderView_UpdateViewVectors();
 
@@ -9896,7 +6762,7 @@ void R_RenderView(void)
        r_refdef.view.clear = true;
 
        // this produces a bloom texture to be used in R_BlendView() later
-       if (r_hdr.integer && r_bloomstate.bloomwidth)
+       if (r_bloomstate.hdr)
        {
                R_HDR_RenderBloomTexture();
                // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
@@ -10155,11 +7021,14 @@ void R_RenderScene(void)
                }
        }
 
-       R_MeshQueue_RenderTransparent();
-       if (r_timereport_active)
-               R_TimeReport("drawtrans");
+       if (r_transparent.integer)
+       {
+               R_MeshQueue_RenderTransparent();
+               if (r_timereport_active)
+                       R_TimeReport("drawtrans");
+       }
 
-       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))
+       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 || r_showoverdraw.value > 0))
        {
                r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
                if (r_timereport_active)
@@ -10249,7 +7118,7 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa
        }
        R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
        R_Mesh_ResetTextureState();
-       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
        R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
 }
 
@@ -10265,14 +7134,14 @@ static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtligh
                return;
 
        GL_CullFace(GL_NONE);
-       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
 
        prog = 0;
        SV_VM_Begin();
        for (i = 0;i < numsurfaces;i++)
        {
                edict = PRVM_EDICT_NUM(surfacelist[i]);
-               switch ((int)edict->fields.server->solid)
+               switch ((int)PRVM_serveredictfloat(edict, solid))
                {
                        case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
                        case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
@@ -10310,9 +7179,9 @@ static void R_DrawEntityBBoxes(void)
                if (edict->priv.server->free)
                        continue;
                // exclude the following for now, as they don't live in world coordinate space and can't be solid:
-               if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
+               if(PRVM_serveredictedict(edict, tag_entity) != 0)
                        continue;
-               if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
+               if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
                        continue;
                VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
                R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
@@ -10415,7 +7284,7 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight
                }
        }
 //     R_Mesh_ResetTextureState();
-       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
        R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
        R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
 }
@@ -10603,7 +7472,7 @@ static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
 {
        double index, f;
-       index = parms[2] + r_refdef.scene.time * parms[3];
+       index = parms[2] + rsurface.shadertime * parms[3];
        index -= floor(index);
        switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
        {
@@ -10639,7 +7508,8 @@ static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
 {
        int w, h, idx;
-       float f;
+       double f;
+       double offsetd[2];
        float tcmat[12];
        matrix4x4_t matrix, temp;
        switch(tcmod->tcmod)
@@ -10658,19 +7528,22 @@ void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *t
                        break;
                case Q3TCMOD_ROTATE:
                        Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
-                       Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
+                       Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
                        Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
                        break;
                case Q3TCMOD_SCALE:
                        Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
                        break;
                case Q3TCMOD_SCROLL:
-                       Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
+                       // extra care is needed because of precision breakdown with large values of time
+                       offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
+                       offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
+                       Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
                        break;
                case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
                        w = (int) tcmod->parms[0];
                        h = (int) tcmod->parms[1];
-                       f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
+                       f = rsurface.shadertime / (tcmod->parms[2] * w * h);
                        f = f - floor(f);
                        idx = (int) floor(f * w * h);
                        Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
@@ -10697,7 +7570,7 @@ void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *t
 
 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
 {
-       int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
+       int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
        char name[MAX_QPATH];
        skinframe_t *skinframe;
        unsigned char pixels[296*194];
@@ -10748,7 +7621,7 @@ texture_t *R_GetCurrentTexture(texture_t *t)
                if (model->skinscenes)
                {
                        if (model->skinscenes[s].framecount > 1)
-                               s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
+                               s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
                        else
                                s = model->skinscenes[s].firstframe;
                }
@@ -10759,9 +7632,9 @@ texture_t *R_GetCurrentTexture(texture_t *t)
                        // use an alternate animation if the entity's frame is not 0,
                        // and only if the texture has an alternate animation
                        if (rsurface.ent_alttextures && t->anim_total[1])
-                               t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
+                               t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
                        else
-                               t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
+                               t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
                }
                texture->currentframe = t;
        }
@@ -10781,16 +7654,16 @@ texture_t *R_GetCurrentTexture(texture_t *t)
                        R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
                t->currentskinframe = r_qwskincache[i].skinframe;
                if (t->currentskinframe == NULL)
-                       t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
+                       t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
        }
        else if (t->numskinframes >= 2)
-               t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
+               t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
        if (t->backgroundnumskinframes >= 2)
-               t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
+               t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
 
        t->currentmaterialflags = t->basematerialflags;
        t->currentalpha = rsurface.colormod[3];
-       if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
+       if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
                t->currentalpha *= r_wateralpha.value;
        if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
                t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
@@ -10800,7 +7673,7 @@ texture_t *R_GetCurrentTexture(texture_t *t)
                t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
        else if (FAKELIGHT_ENABLED)
        {
-                       // no modellight if using fakelight for the map
+               // no modellight if using fakelight for the map
        }
        else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
        {
@@ -10827,6 +7700,11 @@ texture_t *R_GetCurrentTexture(texture_t *t)
        }
        else
                t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
+       if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
+       {
+               // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
+               t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
+       }
        if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
                t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
 
@@ -10952,7 +7830,7 @@ texture_t *R_GetCurrentTexture(texture_t *t)
                        blendfunc2 = GL_ZERO;
                }
                // don't colormod evilblend textures
-               if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
+               if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
                        VectorSet(t->lightmapcolor, 1, 1, 1);
                depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
                if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
@@ -11031,8 +7909,8 @@ void RSurf_ActiveWorldEntity(void)
        memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
        rsurface.ent_skinnum = 0;
        rsurface.ent_qwskin = -1;
-       rsurface.ent_shadertime = 0;
        rsurface.ent_flags = r_refdef.scene.worldentity->flags;
+       rsurface.shadertime = r_refdef.scene.time;
        rsurface.matrix = identitymatrix;
        rsurface.inversematrix = identitymatrix;
        rsurface.matrixscale = 1;
@@ -11142,8 +8020,8 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
        memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
        rsurface.ent_skinnum = ent->skinnum;
        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;
-       rsurface.ent_shadertime = ent->shadertime;
        rsurface.ent_flags = ent->flags;
+       rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
        rsurface.matrix = ent->matrix;
        rsurface.inversematrix = ent->inversematrix;
        rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
@@ -11172,7 +8050,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
                rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
                rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
        }
-       if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
+       if (model->surfmesh.isanimated && model->AnimateVertices)
        {
                if (ent->animcache_vertex3f)
                {
@@ -11186,10 +8064,10 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
                }
                else if (wanttangents)
                {
-                       rsurface.modelvertex3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
-                       rsurface.modelsvector3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
-                       rsurface.modeltvector3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
-                       rsurface.modelnormal3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
+                       rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
+                       rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
+                       rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
+                       rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
                        model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
                        rsurface.modelvertexmesh = NULL;
                        rsurface.modelvertexmeshbuffer = NULL;
@@ -11197,10 +8075,10 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
                }
                else if (wantnormals)
                {
-                       rsurface.modelvertex3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
+                       rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
                        rsurface.modelsvector3f = NULL;
                        rsurface.modeltvector3f = NULL;
-                       rsurface.modelnormal3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
+                       rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
                        model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
                        rsurface.modelvertexmesh = NULL;
                        rsurface.modelvertexmeshbuffer = NULL;
@@ -11208,7 +8086,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
                }
                else
                {
-                       rsurface.modelvertex3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
+                       rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
                        rsurface.modelsvector3f = NULL;
                        rsurface.modeltvector3f = NULL;
                        rsurface.modelnormal3f = NULL;
@@ -11311,8 +8189,8 @@ void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inve
        rsurface.skeleton = NULL;
        rsurface.ent_skinnum = 0;
        rsurface.ent_qwskin = -1;
-       rsurface.ent_shadertime = shadertime;
        rsurface.ent_flags = entflags;
+       rsurface.shadertime = r_refdef.scene.time - shadertime;
        rsurface.modelnumvertices = numvertices;
        rsurface.modelnumtriangles = numtriangles;
        rsurface.matrix = *matrix;
@@ -11341,16 +8219,16 @@ void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inve
        if (wanttangents)
        {
                rsurface.modelvertex3f = (float *)vertex3f;
-               rsurface.modelsvector3f = svector3f ? (float *)svector3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
-               rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
-               rsurface.modelnormal3f = normal3f ? (float *)normal3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
+               rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
+               rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
+               rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
        }
        else if (wantnormals)
        {
                rsurface.modelvertex3f = (float *)vertex3f;
                rsurface.modelsvector3f = NULL;
                rsurface.modeltvector3f = NULL;
-               rsurface.modelnormal3f = normal3f ? (float *)normal3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
+               rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
        }
        else
        {
@@ -11431,13 +8309,13 @@ void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inve
        {
                if ((wantnormals || wanttangents) && !normal3f)
                {
-                       rsurface.modelnormal3f = R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
+                       rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
                        Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
                }
                if (wanttangents && !svector3f)
                {
-                       rsurface.modelsvector3f = R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
-                       rsurface.modeltvector3f = R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
+                       rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
+                       rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
                        Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
                }
        }
@@ -11558,7 +8436,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
        }
 
-       for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
+       for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
        {
                switch (deform->deform)
                {
@@ -11727,7 +8605,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                if (gaps)
                {
                        // build a new triangle elements array for this batch
-                       rsurface.batchelement3i = R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
+                       rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
                        rsurface.batchfirsttriangle = 0;
                        numtriangles = 0;
                        for (i = 0;i < texturenumsurfaces;i++)
@@ -11745,7 +8623,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                        if (endvertex <= 65536)
                        {
                                // make a 16bit (unsigned short) index array if possible
-                               rsurface.batchelement3s = R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
+                               rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
                                for (i = 0;i < numtriangles*3;i++)
                                        rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
                        }
@@ -11786,7 +8664,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                rsurface.batchtexcoordlightmap2f = NULL;
                rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
                rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
-               rsurface.batchelement3i = R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
+               rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
                rsurface.batchelement3i_indexbuffer = NULL;
                rsurface.batchelement3i_bufferoffset = 0;
                rsurface.batchelement3s = NULL;
@@ -11794,22 +8672,22 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                rsurface.batchelement3s_bufferoffset = 0;
                // we'll only be setting up certain arrays as needed
                if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
-                       rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
+                       rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
                if (batchneed & BATCHNEED_ARRAY_VERTEX)
-                       rsurface.batchvertex3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
+                       rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
                if (batchneed & BATCHNEED_ARRAY_NORMAL)
-                       rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
+                       rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
                if (batchneed & BATCHNEED_ARRAY_VECTOR)
                {
-                       rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
-                       rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
+                       rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
+                       rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
                }
                if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
-                       rsurface.batchlightmapcolor4f = R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
+                       rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
                if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
-                       rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
+                       rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
                if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
-                       rsurface.batchtexcoordlightmap2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
+                       rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
                numvertices = 0;
                numtriangles = 0;
                for (i = 0;i < texturenumsurfaces;i++)
@@ -11824,20 +8702,53 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                        if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
                        {
                                if (batchneed & BATCHNEED_ARRAY_VERTEX)
-                                       memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
-                               if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
-                                       memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
-                               if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
                                {
-                                       memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
-                                       memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+                                       if (rsurface.batchvertex3f)
+                                               memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+                                       else
+                                               memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
+                               }
+                               if (batchneed & BATCHNEED_ARRAY_NORMAL)
+                               {
+                                       if (rsurface.modelnormal3f)
+                                               memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+                                       else
+                                               memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
+                               }
+                               if (batchneed & BATCHNEED_ARRAY_VECTOR)
+                               {
+                                       if (rsurface.modelsvector3f)
+                                       {
+                                               memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+                                               memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+                                       }
+                                       else
+                                       {
+                                               memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
+                                               memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
+                                       }
+                               }
+                               if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
+                               {
+                                       if (rsurface.modellightmapcolor4f)
+                                               memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
+                                       else
+                                               memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
+                               }
+                               if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
+                               {
+                                       if (rsurface.modeltexcoordtexture2f)
+                                               memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
+                                       else
+                                               memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
+                               }
+                               if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
+                               {
+                                       if (rsurface.modeltexcoordlightmap2f)
+                                               memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
+                                       else
+                                               memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
                                }
-                               if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
-                                       memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
-                               if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
-                                       memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
-                               if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
-                                       memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
                        }
                        RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
                        numvertices += surfacenumvertices;
@@ -11848,7 +8759,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                // (in general, dynamic batches fit)
                if (numvertices <= 65536)
                {
-                       rsurface.batchelement3s = R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
+                       rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
                        for (i = 0;i < numtriangles*3;i++)
                                rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
                }
@@ -11870,7 +8781,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                int size3;
                const int *offsets;
                const unsigned char *lm;
-               rsurface.batchlightmapcolor4f = R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
+               rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
                rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
                rsurface.batchlightmapcolor4f_bufferoffset = 0;
                numvertices = 0;
@@ -11905,9 +8816,9 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                                                        }
                                                }
                                        }
-                                       c[0] >>= 15;
-                                       c[1] >>= 15;
-                                       c[2] >>= 15;
+                                       c[0] >>= 7;
+                                       c[1] >>= 7;
+                                       c[2] >>= 7;
                                        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);
                                        numvertices++;
                                }
@@ -11926,7 +8837,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
        // if vertices are deformed (sprite flares and things in maps, possibly
        // water waves, bulges and other deformations), modify the copied vertices
        // in place
-       for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
+       for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
        {
                switch (deform->deform)
                {
@@ -11961,6 +8872,11 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
 //                     rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
 //                     rsurface.batchnormal3f_vertexbuffer = NULL;
 //                     rsurface.batchnormal3f_bufferoffset = 0;
+                       // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
+                       if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
+                               Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
+                       if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
+                               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);
                        // a single autosprite surface can contain multiple sprites...
                        for (j = 0;j < batchnumvertices - 3;j += 4)
                        {
@@ -12089,7 +9005,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                        break;
                case Q3DEFORM_NORMAL:
                        // deform the normals to make reflections wavey
-                       rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
+                       rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
                        rsurface.batchnormal3f_vertexbuffer = NULL;
                        rsurface.batchnormal3f_bufferoffset = 0;
                        for (j = 0;j < batchnumvertices;j++)
@@ -12097,9 +9013,9 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                                float vertex[3];
                                float *normal = rsurface.batchnormal3f + 3*j;
                                VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
-                               normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
-                               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]);
-                               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]);
+                               normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
+                               normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
+                               normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
                                VectorNormalize(normal);
                        }
                        if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
@@ -12163,7 +9079,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
 //                     rsurface.batchnormal3f_bufferoffset = 0;
                        for (j = 0;j < batchnumvertices;j++)
                        {
-                               scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
+                               scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
                                VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
                        }
                        // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
@@ -12219,9 +9135,9 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                break;
        case Q3TCGEN_ENVIRONMENT:
                // make environment reflections using a spheremap
-//             rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
-//             rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
-//             rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+               rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
+               rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+               rsurface.batchtexcoordtexture2f_bufferoffset = 0;
                for (j = 0;j < batchnumvertices;j++)
                {
                        // identical to Q3A's method, but executed in worldspace so
@@ -12257,7 +9173,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
        if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
        {
                amplitude = rsurface.texture->tcmods[0].parms[1];
-               animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
+               animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
 //             rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
 //             rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
 //             rsurface.batchtexcoordtexture2f_bufferoffset = 0;
@@ -12289,7 +9205,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const
                }
                if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
                        for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
-                               Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
+                               Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
                if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
                        for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
                                Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
@@ -12377,7 +9293,7 @@ static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
 {
        int i;
-       rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
+       rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
        rsurface.passcolor4f_vertexbuffer = 0;
        rsurface.passcolor4f_bufferoffset = 0;
        for (i = 0;i < rsurface.batchnumvertices;i++)
@@ -12391,12 +9307,13 @@ static void RSurf_DrawBatch_GL11_ApplyFog(void)
        const float *v;
        const float *c;
        float *c2;
-       rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
-       rsurface.passcolor4f_vertexbuffer = 0;
-       rsurface.passcolor4f_bufferoffset = 0;
        if (rsurface.passcolor4f)
        {
                // generate color arrays
+               c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
+               rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
+               rsurface.passcolor4f_vertexbuffer = 0;
+               rsurface.passcolor4f_bufferoffset = 0;
                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)
                {
                        f = RSurf_FogVertex(v);
@@ -12408,6 +9325,9 @@ static void RSurf_DrawBatch_GL11_ApplyFog(void)
        }
        else
        {
+               rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
+               rsurface.passcolor4f_vertexbuffer = 0;
+               rsurface.passcolor4f_bufferoffset = 0;
                for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
                {
                        f = RSurf_FogVertex(v);
@@ -12428,10 +9348,11 @@ static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
        float *c2;
        if (!rsurface.passcolor4f)
                return;
-       rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
+       c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
+       rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
        rsurface.passcolor4f_vertexbuffer = 0;
        rsurface.passcolor4f_bufferoffset = 0;
-       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)
+       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)
        {
                f = RSurf_FogVertex(v);
                c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
@@ -12448,10 +9369,11 @@ static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
        float *c2;
        if (!rsurface.passcolor4f)
                return;
-       rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
+       c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
+       rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
        rsurface.passcolor4f_vertexbuffer = 0;
        rsurface.passcolor4f_bufferoffset = 0;
-       for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
+       for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
        {
                c2[0] = c[0] * r;
                c2[1] = c[1] * g;
@@ -12467,10 +9389,11 @@ static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
        float *c2;
        if (!rsurface.passcolor4f)
                return;
-       rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
+       c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
+       rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
        rsurface.passcolor4f_vertexbuffer = 0;
        rsurface.passcolor4f_bufferoffset = 0;
-       for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
+       for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
        {
                c2[0] = c[0] + r_refdef.scene.ambient;
                c2[1] = c[1] + r_refdef.scene.ambient;
@@ -12546,7 +9469,7 @@ static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
        //vec3_t eyedir;
 
        // fake shading
-       rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
+       rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
        rsurface.passcolor4f_vertexbuffer = 0;
        rsurface.passcolor4f_bufferoffset = 0;
        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)
@@ -12594,7 +9517,7 @@ static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b,
        if (VectorLength2(diffusecolor) > 0)
        {
                // q3-style directional shading
-               rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
+               rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
                rsurface.passcolor4f_vertexbuffer = 0;
                rsurface.passcolor4f_bufferoffset = 0;
                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)
@@ -12638,6 +9561,12 @@ static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a
        float f;
        const float *v;
        float *c;
+
+       // fake shading
+       rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
+       rsurface.passcolor4f_vertexbuffer = 0;
+       rsurface.passcolor4f_bufferoffset = 0;
+
        for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
        {
                f = 1 - RSurf_FogVertex(v);
@@ -12664,7 +9593,7 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_
        // transparent sky would be ridiculous
        if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
                return;
-       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
        skyrenderlater = true;
        RSurf_SetupDepthAndCulling();
        GL_DepthMask(true);
@@ -12674,12 +9603,12 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_
        // in Quake3 maps as it causes problems with q3map2 sky tricks,
        // and skymasking also looks very bad when noclipping outside the
        // level, so don't use it then either.
-       if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
+       if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
        {
                R_Mesh_ResetTextureState();
                if (skyrendermasked)
                {
-                       R_SetupShader_DepthOrShadow();
+                       R_SetupShader_DepthOrShadow(false);
                        // depth-only (masking)
                        GL_ColorMask(0,0,0,0);
                        // just to make sure that braindead drivers don't draw
@@ -12693,7 +9622,7 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_
                }
                else
                {
-                       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+                       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
                        // fog sky
                        GL_BlendFunc(GL_ONE, GL_ZERO);
                        RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
@@ -12718,9 +9647,8 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface
        {
                // render screenspace normalmap to texture
                GL_DepthMask(true);
-               R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
+               R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
                RSurf_DrawBatch();
-               return;
        }
 
        // bind lightmap texture
@@ -12746,18 +9674,18 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface
                        {
                                // render water or distortion background
                                GL_DepthMask(true);
-                               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));
+                               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), false);
                                RSurf_DrawBatch();
                                // blend surface on top
                                GL_DepthMask(false);
-                               R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
+                               R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
                                RSurf_DrawBatch();
                        }
                        else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
                        {
                                // render surface with reflection texture as input
                                GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
-                               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));
+                               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), false);
                                RSurf_DrawBatch();
                        }
                }
@@ -12766,7 +9694,7 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface
 
        // render surface batch normally
        GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
-       R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
+       R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
        RSurf_DrawBatch();
 }
 
@@ -12988,9 +9916,8 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const
        r_vertexgeneric_t *batchvertex;
        float c[4];
 
-       GL_AlphaTest(false);
 //     R_Mesh_ResetTextureState();
-       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
 
        if(rsurface.texture && rsurface.texture->currentskinframe)
        {
@@ -13096,7 +10023,7 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const
                RSurf_DrawBatch_GL11_ClampColor();
 
                R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
-               R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+               R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
                RSurf_DrawBatch();
        }
        else if (!r_refdef.view.showdebug)
@@ -13106,7 +10033,7 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const
                for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
                {
                        VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
-                       Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
+                       Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
                }
                R_Mesh_PrepareVertices_Generic_Unlock();
                RSurf_DrawBatch();
@@ -13117,9 +10044,9 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const
                batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
                for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
                {
-                       unsigned char c = vi << 3;
+                       unsigned char c = (vi << 3) * (1.0f / 256.0f);
                        VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
-                       Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
+                       Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
                }
                R_Mesh_PrepareVertices_Generic_Unlock();
                RSurf_DrawBatch();
@@ -13131,13 +10058,13 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const
                batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
                for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
                {
-                       unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
+                       unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
                        VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
                        VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
                        VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
-                       Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
-                       Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
-                       Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
+                       Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
+                       Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
+                       Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
                }
                R_Mesh_PrepareVertices_Generic_Unlock();
                R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
@@ -13147,7 +10074,7 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const
                int texturesurfaceindex;
                int k;
                const msurface_t *surface;
-               unsigned char surfacecolor4ub[4];
+               float surfacecolor4f[4];
                RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
                batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
                vi = 0;
@@ -13155,11 +10082,11 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const
                {
                        surface = texturesurfacelist[texturesurfaceindex];
                        k = (int)(((size_t)surface) / sizeof(msurface_t));
-                       Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
+                       Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
                        for (j = 0;j < surface->num_vertices;j++)
                        {
                                VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
-                               Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
+                               Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
                                vi++;
                        }
                }
@@ -13180,14 +10107,15 @@ static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface
        switch (vid.renderpath)
        {
        case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
                break;
        case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
                break;
        case RENDERPATH_GL11:
@@ -13209,14 +10137,15 @@ static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface
        switch (vid.renderpath)
        {
        case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
        case RENDERPATH_D3D9:
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
                R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
                break;
        case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
                R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
                break;
        case RENDERPATH_GL11:
@@ -13232,8 +10161,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const
        int texturenumsurfaces, endsurface;
        texture_t *texture;
        const msurface_t *surface;
-#define MAXBATCH_TRANSPARENTSURFACES 256
-       const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
+       const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
 
        // if the model is static it doesn't matter what value we give for
        // wantnormals and wanttangents, so this logic uses only rules applicable
@@ -13247,15 +10175,16 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const
                switch (vid.renderpath)
                {
                case RENDERPATH_GL20:
-               case RENDERPATH_CGGL:
                case RENDERPATH_D3D9:
                case RENDERPATH_D3D10:
                case RENDERPATH_D3D11:
                case RENDERPATH_SOFT:
+               case RENDERPATH_GLES2:
                        RSurf_ActiveModelEntity(ent, true, true, false);
                        break;
-               case RENDERPATH_GL13:
                case RENDERPATH_GL11:
+               case RENDERPATH_GL13:
+               case RENDERPATH_GLES1:
                        RSurf_ActiveModelEntity(ent, true, false, false);
                        break;
                }
@@ -13295,9 +10224,8 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const
                                GL_DepthTest(true);
                                GL_BlendFunc(GL_ONE, GL_ZERO);
                                GL_DepthMask(true);
-                               GL_AlphaTest(false);
 //                             R_Mesh_ResetTextureState();
-                               R_SetupShader_DepthOrShadow();
+                               R_SetupShader_DepthOrShadow(false);
                        }
                        RSurf_SetupDepthAndCulling();
                        RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
@@ -13318,7 +10246,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const
                texture = surface->texture;
                rsurface.texture = R_GetCurrentTexture(texture);
                // scan ahead until we find a different texture
-               endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
+               endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
                texturenumsurfaces = 0;
                texturesurfacelist[texturenumsurfaces++] = surface;
                if(FAKELIGHT_ENABLED)
@@ -13354,7 +10282,6 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const
                        R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
        }
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
-       GL_AlphaTest(false);
 }
 
 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
@@ -13410,7 +10337,7 @@ static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurf
                else
                        R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
        }
-       else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
+       else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
                R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
        else if (!rsurface.texture->currentnumlayers)
                return;
@@ -13488,7 +10415,7 @@ static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurf
                else
                        R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
        }
-       else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
+       else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
                R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
        else if (!rsurface.texture->currentnumlayers)
                return;
@@ -13611,7 +10538,7 @@ void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, in
                        vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
 
        R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
-       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
        R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
 }
 
@@ -13668,7 +10595,7 @@ static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float
        // grab a decal and search for another free slot for the next one
        decals = decalsystem->decals;
        decal = decalsystem->decals + (i = decalsystem->freedecal++);
-       for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
+       for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
                ;
        decalsystem->freedecal = i;
        if (decalsystem->numdecals <= i)
@@ -13679,18 +10606,18 @@ static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float
        decal->triangleindex = triangleindex;
        decal->surfaceindex = surfaceindex;
        decal->decalsequence = decalsequence;
-       decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
-       decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
-       decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
-       decal->color4ub[0][3] = 255;
-       decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
-       decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
-       decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
-       decal->color4ub[1][3] = 255;
-       decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
-       decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
-       decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
-       decal->color4ub[2][3] = 255;
+       decal->color4f[0][0] = c0[0];
+       decal->color4f[0][1] = c0[1];
+       decal->color4f[0][2] = c0[2];
+       decal->color4f[0][3] = 1;
+       decal->color4f[1][0] = c1[0];
+       decal->color4f[1][1] = c1[1];
+       decal->color4f[1][2] = c1[2];
+       decal->color4f[1][3] = 1;
+       decal->color4f[2][0] = c2[0];
+       decal->color4f[2][1] = c2[1];
+       decal->color4f[2][2] = c2[2];
+       decal->color4f[2][3] = 1;
        decal->vertex3f[0][0] = v0[0];
        decal->vertex3f[0][1] = v0[1];
        decal->vertex3f[0][2] = v0[2];
@@ -13706,6 +10633,9 @@ static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float
        decal->texcoord2f[1][1] = t1[1];
        decal->texcoord2f[2][0] = t2[0];
        decal->texcoord2f[2][1] = t2[1];
+       TriangleNormal(v0, v1, v2, decal->plane);
+       VectorNormalize(decal->plane);
+       decal->plane[3] = DotProduct(v0, decal->plane);
 }
 
 extern cvar_t cl_decals_bias;
@@ -13718,6 +10648,7 @@ static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, flo
        int index;
        float v[9][3];
        const float *vertex3f;
+       const float *normal3f;
        int numpoints;
        float points[2][9][3];
        float temp[3];
@@ -13729,12 +10660,25 @@ static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, flo
        e = rsurface.modelelement3i + 3*triangleindex;
 
        vertex3f = rsurface.modelvertex3f;
+       normal3f = rsurface.modelnormal3f;
 
-       for (cornerindex = 0;cornerindex < 3;cornerindex++)
+       if (normal3f)
        {
-               index = 3*e[cornerindex];
-               VectorCopy(vertex3f + index, v[cornerindex]);
+               for (cornerindex = 0;cornerindex < 3;cornerindex++)
+               {
+                       index = 3*e[cornerindex];
+                       VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
+               }
+       }
+       else
+       {
+               for (cornerindex = 0;cornerindex < 3;cornerindex++)
+               {
+                       index = 3*e[cornerindex];
+                       VectorCopy(vertex3f + index, v[cornerindex]);
+               }
        }
+
        // cull backfaces
        //TriangleNormal(v[0], v[1], v[2], normal);
        //if (DotProduct(normal, localnormal) < 0.0f)
@@ -13838,7 +10782,7 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor
                R_DecalSystem_Reset(decalsystem);
        decalsystem->model = model;
 
-       RSurf_ActiveModelEntity(ent, false, false, false);
+       RSurf_ActiveModelEntity(ent, true, false, false);
 
        Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
        Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
@@ -14048,16 +10992,16 @@ static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
        lifetime = cl_decals_time.value + cl_decals_fadetime.value;
 
        if (decalsystem->lastupdatetime)
-               frametime = (cl.time - decalsystem->lastupdatetime);
+               frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
        else
                frametime = 0;
-       decalsystem->lastupdatetime = cl.time;
+       decalsystem->lastupdatetime = r_refdef.scene.time;
        decal = decalsystem->decals;
        numdecals = decalsystem->numdecals;
 
        for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
        {
-               if (decal->color4ub[0][3])
+               if (decal->color4f[0][3])
                {
                        decal->lived += frametime;
                        if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
@@ -14069,13 +11013,13 @@ static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
                }
        }
        decal = decalsystem->decals;
-       while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
+       while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
                numdecals--;
 
        // collapse the array by shuffling the tail decals into the gaps
        for (;;)
        {
-               while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
+               while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
                        decalsystem->freedecal++;
                if (decalsystem->freedecal == numdecals)
                        break;
@@ -14128,7 +11072,7 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent)
        else
                RSurf_ActiveModelEntity(ent, false, false, false);
 
-       decalsystem->lastupdatetime = cl.time;
+       decalsystem->lastupdatetime = r_refdef.scene.time;
        decal = decalsystem->decals;
 
        faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
@@ -14139,32 +11083,33 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent)
        t2f = decalsystem->texcoord2f;
        for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
        {
-               if (!decal->color4ub[0][3])
+               if (!decal->color4f[0][3])
                        continue;
 
                if (surfacevisible && !surfacevisible[decal->surfaceindex])
                        continue;
 
+               // skip backfaces
+               if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
+                       continue;
+
                // update color values for fading decals
                if (decal->lived >= cl_decals_time.value)
-               {
                        alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
-                       alpha *= (1.0f/255.0f);
-               }
                else
-                       alpha = 1.0f/255.0f;
+                       alpha = 1.0f;
 
-               c4f[ 0] = decal->color4ub[0][0] * alpha;
-               c4f[ 1] = decal->color4ub[0][1] * alpha;
-               c4f[ 2] = decal->color4ub[0][2] * alpha;
+               c4f[ 0] = decal->color4f[0][0] * alpha;
+               c4f[ 1] = decal->color4f[0][1] * alpha;
+               c4f[ 2] = decal->color4f[0][2] * alpha;
                c4f[ 3] = 1;
-               c4f[ 4] = decal->color4ub[1][0] * alpha;
-               c4f[ 5] = decal->color4ub[1][1] * alpha;
-               c4f[ 6] = decal->color4ub[1][2] * alpha;
+               c4f[ 4] = decal->color4f[1][0] * alpha;
+               c4f[ 5] = decal->color4f[1][1] * alpha;
+               c4f[ 6] = decal->color4f[1][2] * alpha;
                c4f[ 7] = 1;
-               c4f[ 8] = decal->color4ub[2][0] * alpha;
-               c4f[ 9] = decal->color4ub[2][1] * alpha;
-               c4f[10] = decal->color4ub[2][2] * alpha;
+               c4f[ 8] = decal->color4f[2][0] * alpha;
+               c4f[ 9] = decal->color4f[2][1] * alpha;
+               c4f[10] = decal->color4f[2][2] * alpha;
                c4f[11] = 1;
 
                t2f[0] = decal->texcoord2f[0][0];
@@ -14211,7 +11156,7 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent)
 
                // now render the decals all at once
                // (this assumes they all use one particle font texture!)
-               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);
+               RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
 //             R_Mesh_ResetTextureState();
                R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
                GL_DepthMask(false);
@@ -14220,7 +11165,7 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent)
                GL_DepthTest(true);
                GL_CullFace(GL_NONE);
                GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
-               R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
+               R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
                R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
        }
 }
@@ -14270,31 +11215,44 @@ void R_DrawDebugModel(void)
        dp_model_t *model = ent->model;
        vec3_t v;
 
-       switch(vid.renderpath)
-       {
-       case RENDERPATH_GL11:
-       case RENDERPATH_GL13:
-       case RENDERPATH_GL20:
-       case RENDERPATH_CGGL:
-               break;
-       case RENDERPATH_D3D9:
-               //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
-               return;
-       case RENDERPATH_D3D10:
-               Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
-               return;
-       case RENDERPATH_D3D11:
-               Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
-               return;
-       case RENDERPATH_SOFT:
-               //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+       if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
                return;
+
+       if (r_showoverdraw.value > 0)
+       {
+               float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
+               flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
+               R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
+               GL_DepthTest(false);
+               GL_DepthMask(false);
+               GL_DepthRange(0, 1);
+               GL_BlendFunc(GL_ONE, GL_ONE);
+               for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+               {
+                       if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
+                               continue;
+                       rsurface.texture = R_GetCurrentTexture(surface->texture);
+                       if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
+                       {
+                               RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
+                               GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
+                               if (!rsurface.texture->currentlayers->depthmask)
+                                       GL_Color(c, 0, 0, 1.0f);
+                               else if (ent == r_refdef.scene.worldentity)
+                                       GL_Color(c, c, c, 1.0f);
+                               else
+                                       GL_Color(0, c, 0, 1.0f);
+                               R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
+                               RSurf_DrawBatch();
+                       }
+               }
+               rsurface.texture = NULL;
        }
 
        flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
 
 //     R_Mesh_ResetTextureState();
-       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+       R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
        GL_DepthRange(0, 1);
        GL_DepthTest(!r_showdisabledepthtest.integer);
        GL_DepthMask(false);
@@ -14350,7 +11308,7 @@ void R_DrawDebugModel(void)
 
        GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
 
-       if (r_showtris.integer || (r_shownormals.value != 0))
+       if (r_showtris.integer && qglPolygonMode)
        {
                if (r_showdisabledepthtest.integer)
                {
@@ -14362,6 +11320,7 @@ void R_DrawDebugModel(void)
                        GL_BlendFunc(GL_ONE, GL_ZERO);
                        GL_DepthMask(true);
                }
+               qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
                for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
                {
                        if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
@@ -14370,23 +11329,43 @@ void R_DrawDebugModel(void)
                        if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
                        {
                                RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
-                               if (r_showtris.value > 0)
-                               {
-                                       if (!rsurface.texture->currentlayers->depthmask)
-                                               GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
-                                       else if (ent == r_refdef.scene.worldentity)
-                                               GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
-                                       else
-                                               GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
-                                       R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
-                                       qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-                                       RSurf_DrawBatch();
-                                       qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-                                       CHECKGLERROR
-                               }
-                               if (r_shownormals.value < 0)
+                               if (!rsurface.texture->currentlayers->depthmask)
+                                       GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
+                               else if (ent == r_refdef.scene.worldentity)
+                                       GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
+                               else
+                                       GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
+                               R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
+                               RSurf_DrawBatch();
+                       }
+               }
+               qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
+               rsurface.texture = NULL;
+       }
+
+       if (r_shownormals.value != 0 && qglBegin)
+       {
+               if (r_showdisabledepthtest.integer)
+               {
+                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                       GL_DepthMask(false);
+               }
+               else
+               {
+                       GL_BlendFunc(GL_ONE, GL_ZERO);
+                       GL_DepthMask(true);
+               }
+               for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+               {
+                       if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
+                               continue;
+                       rsurface.texture = R_GetCurrentTexture(surface->texture);
+                       if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
+                       {
+                               RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
+                               qglBegin(GL_LINES);
+                               if (r_shownormals.value < 0 && rsurface.batchnormal3f)
                                {
-                                       qglBegin(GL_LINES);
                                        for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
                                        {
                                                VectorCopy(rsurface.batchvertex3f + l * 3, v);
@@ -14396,12 +11375,9 @@ void R_DrawDebugModel(void)
                                                GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
                                                qglVertex3f(v[0], v[1], v[2]);
                                        }
-                                       qglEnd();
-                                       CHECKGLERROR
                                }
                                if (r_shownormals.value > 0 && rsurface.batchsvector3f)
                                {
-                                       qglBegin(GL_LINES);
                                        for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
                                        {
                                                VectorCopy(rsurface.batchvertex3f + l * 3, v);
@@ -14411,9 +11387,9 @@ void R_DrawDebugModel(void)
                                                GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
                                                qglVertex3f(v[0], v[1], v[2]);
                                        }
-                                       qglEnd();
-                                       CHECKGLERROR
-                                       qglBegin(GL_LINES);
+                               }
+                               if (r_shownormals.value > 0 && rsurface.batchtvector3f)
+                               {
                                        for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
                                        {
                                                VectorCopy(rsurface.batchvertex3f + l * 3, v);
@@ -14423,9 +11399,9 @@ void R_DrawDebugModel(void)
                                                GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
                                                qglVertex3f(v[0], v[1], v[2]);
                                        }
-                                       qglEnd();
-                                       CHECKGLERROR
-                                       qglBegin(GL_LINES);
+                               }
+                               if (r_shownormals.value > 0 && rsurface.batchnormal3f)
+                               {
                                        for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
                                        {
                                                VectorCopy(rsurface.batchvertex3f + l * 3, v);
@@ -14435,9 +11411,9 @@ void R_DrawDebugModel(void)
                                                GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
                                                qglVertex3f(v[0], v[1], v[2]);
                                        }
-                                       qglEnd();
-                                       CHECKGLERROR
                                }
+                               qglEnd();
+                               CHECKGLERROR
                        }
                }
                rsurface.texture = NULL;
@@ -14530,7 +11506,6 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep
                return;
        }
        R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
-       GL_AlphaTest(false);
 
        // add to stats if desired
        if (r_speeds.integer && !skysurfaces && !depthonly)
@@ -14575,15 +11550,16 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
                switch (vid.renderpath)
                {
                case RENDERPATH_GL20:
-               case RENDERPATH_CGGL:
                case RENDERPATH_D3D9:
                case RENDERPATH_D3D10:
                case RENDERPATH_D3D11:
                case RENDERPATH_SOFT:
+               case RENDERPATH_GLES2:
                        RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
                        break;
-               case RENDERPATH_GL13:
                case RENDERPATH_GL11:
+               case RENDERPATH_GL13:
+               case RENDERPATH_GLES1:
                        RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
                        break;
                }
@@ -14593,15 +11569,16 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
                switch (vid.renderpath)
                {
                case RENDERPATH_GL20:
-               case RENDERPATH_CGGL:
                case RENDERPATH_D3D9:
                case RENDERPATH_D3D10:
                case RENDERPATH_D3D11:
                case RENDERPATH_SOFT:
+               case RENDERPATH_GLES2:
                        RSurf_ActiveModelEntity(ent, true, true, false);
                        break;
-               case RENDERPATH_GL13:
                case RENDERPATH_GL11:
+               case RENDERPATH_GL13:
+               case RENDERPATH_GLES1:
                        RSurf_ActiveModelEntity(ent, true, false, false);
                        break;
                }
@@ -14668,7 +11645,6 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr
                        if (update[j])
                                R_BuildLightMap(ent, surfaces + j);
        R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
-       GL_AlphaTest(false);
 
        // add to stats if desired
        if (r_speeds.integer && !skysurfaces && !depthonly)