Soft Light Intensity=0.5
Soft Light Blur Strength=1.0
Gaussian Bloom Intensity=1.0
Luma based Bloom=true
Luma Src 1_orig 2_softlight 3_blend=3.0
Gaussian Blur Strength=1.0
Here is the first effect:
- // GUI ELEMENTS
//=================================================================================================================
// EXTERNAL PARAMETERS, DO NOT MODIFY
// UNLESS YOU KNOW WHAT YOU ARE DOING
//=================================================================================================================
// KEYBOARD CONTROLLED TEMPORARY VARIABLES
// Press and hold key 1,2,3...8 together with PageUp or PageDown to modify. By default all set to 1.0
//=================================================================================================================
float4 tempF1; // 0, 1, 2, 3
float4 tempF2; // 5, 6, 7, 8
float4 tempF3; // 9, 0
//=================================================================================================================
// GLOBAL VARIABLES
//=================================================================================================================
float4 Timer; // x = generic timer in range 0..1, period of 16777216 ms (4.6 hours), w = frame time elapsed (in seconds)
float4 ScreenSize; // x = Width, y = 1 / Width, z = ScreenScaleY, w = 1 / ScreenScaleY
float ENightDayFactor; // changes in range 0..1, 0 means that night time, 1 - day time
float EInteriorFactor; // changes 0 or 1. 0 means that exterior, 1 - interior
//=================================================================================================================
// TEXTURES | SAMPLERS
//=================================================================================================================
texture2D texOriginal;
texture2D texColor;
texture2D texNoise;
texture2D texDepth;
sampler2D SamplerColor = sampler_state
{
Texture = <texColor>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = NONE;
AddressU = Clamp;
AddressV = Clamp;
SRGBTexture=FALSE;
MaxMipLevel=0;
MipMapLodBias=0;
};
sampler2D SamplerColor2 = sampler_state
{
Texture = <texOriginal>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = NONE;
AddressU = Clamp;
AddressV = Clamp;
SRGBTexture=FALSE;
MaxMipLevel=0;
MipMapLodBias=0;
};
sampler2D SamplerNoise = sampler_state
{
Texture = <texNoise>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = NONE;
AddressU = Wrap;
AddressV = Wrap;
SRGBTexture=FALSE;
MaxMipLevel=0;
MipMapLodBias=0;
};
sampler2D SamplerDepth = sampler_state
{
Texture = <texDepth>;
MinFilter = POINT;
MagFilter = POINT;
MipFilter = NONE;
AddressU = Clamp;
AddressV = Clamp;
SRGBTexture=FALSE;
MaxMipLevel=0;
MipMapLodBias=0;
};
//=================================================================================================================
// DATA STRUCTURE
//=================================================================================================================
struct VS_OUTPUT_POST
{
float4 vpos : POSITION;
float2 txcoord : TEXCOORD0;
};
struct VS_INPUT_POST
{
float3 pos : POSITION;
float2 txcoord : TEXCOORD0;
};
VS_OUTPUT_POST VS_PostProcess (VS_INPUT_POST IN)
{
VS_OUTPUT_POST OUT;
float4 pos = float4 (IN.pos.x, IN.pos.y, IN.pos.z, 1.0);
OUT.vpos = pos;
OUT.txcoord.xy = IN.txcoord.xy;
return OUT;
}
//=================================================================================================================
// HELPER FUNCTIONS
//=================================================================================================================
// Pseudo Random Number Generator
float random (in float2 uv)
{
float2 noise = (frac (sin (dot (uv, float2 (12.9898, 78.233) * 2.0)) * 43758.5453));
return abs (noise.x + noise.y) * 0.5;
}
// Vignette
float vignette (float2 coord, float _int)
{
float2 coords = coord;
coords = (coords - 0.5) * 2.0;
float coord_dot = dot (coords, coords);
return 1.0 - coord_dot * _int * 0.1;
}
//GAUSSIAN WEIGHTS - Linear sampled for high performance
//9 tap reduced to 3 weights ( 17 pixels wide )
static const float sampleOffsets_1[3] = { 0.0, 1.137453814668, 3.013581103919 };
static const float sampleWeights_1[3] = { 0.441440131387, 0.277468870531, 0.001811063775 };
//17 tap reduced to 5 weights ( 33 pixels wide )
static const float sampleOffsets_2[5] = { 0.0, 1.263686497497, 3.083471450524, 5.022636787155, 7.005855649638 };
static const float sampleWeights_2[5] = { 0.330086281980, 0.318351147970, 0.016540813281, 0.000064880504, 0.000000017255 };
//21 tap reduced to 6 weights ( 41 pixels wide )
static const float sampleOffsets_3[6] = { 0.0, 1.452313744966, 3.390210239952, 5.331472958797, 7.277552900121, 9.229394260785 };
static const float sampleWeights_3[6] = { 0.142479385858, 0.244115579374, 0.131636577371, 0.043283482080, 0.008668409765, 0.001056258481 };
float3 softlight(float3 a, float3 b, float s)
{
float3 ret;
float3 b_x2 = 2.0 * b;
float3 a_b_x2 = a * b_x2;
float3 c1 = a_b_x2 + a * a - a * a_b_x2;
float3 c2 = sqrt(a) * ( b_x2 - 1.0 ) + 2.0 * a - a_b_x2;
ret = ( b >= 0.5 ) ? c1 : c2;
return lerp( a, ret, s );
}
float3 screen(float3 a, float3 b)
{
return (1.0f - (1.0f - a) * (1.0f - b));
}
//=================================================================================================================
// functions
//=================================================================================================================
float linearlizeDepth(float nonlinearDepth)
{
float2 dofProj=float2(0.0509804, 3098.0392);
float2 dofDist=float2(0.0, 0.0509804);
float4 depth=nonlinearDepth;
depth.y=-dofProj.x + dofProj.y;
depth.y=1.0/depth.y;
depth.z=depth.y * dofProj.y;
depth.z=depth.z * -dofProj.x;
depth.x=dofProj.y * -depth.y + depth.x;
depth.x=1.0/depth.x;
depth.y=depth.z * depth.x;
depth.x=depth.z * depth.x - dofDist.y;
depth.x+=dofDist.x * -0.5;
depth.x=max(depth.x, 0.0);
return depth.x;
}
float3 normals(float2 tex)//get normal vector from depthmap
{
float2 pixelSize=ScreenSize.y;
pixelSize.y*=ScreenSize.z;
float deltax = linearlizeDepth( tex2D(SamplerDepth, float2((tex.x + pixelSize.x), tex.y)).x) - linearlizeDepth( tex2D(SamplerDepth, float2((tex.x - pixelSize.x), tex.y)).x);
float deltay = linearlizeDepth(tex2D(SamplerDepth, float2( tex.x, (tex.y + pixelSize.y))).x) - linearlizeDepth(tex2D(SamplerDepth, float2( tex.x, (tex.y - pixelSize.y))).x);
return normalize(float3( (deltax / 2 / pixelSize.x), (deltay / 2 / pixelSize.y) , 1));
}
#define E_SHADER_3_0
float4 Overlay (float4 cBase, float4 cBlend)
{
float4 cNew;
cNew = step(0.5,cBase);
cNew= lerp((cBase*cBlend*2),(1.0-(2.0*(1.0-cBase)*(1.0-cBlend))),cNew);
cNew.a = 1.0;
return cNew;
}
float4 PP2(float4 color, float brightness, float vcontrast, float vsaturation, float toneMappingCurve, float toneMappingCurveOverSaturation)
{
color.xyz*=brightness;
float3 xncol=normalize(color.xyz);
float3 scl=color.xyz/xncol.xyz;
scl=pow(scl, vcontrast);
xncol.xyz=pow(xncol.xyz, vsaturation);
color.xyz=scl*xncol.xyz;
color.xyz=(color.xyz * (1.0 + color.xyz/toneMappingCurveOverSaturation))/(color.xyz + toneMappingCurve);
return color;
}
//=================================================================================================================
// SHADERS
//=================================================================================================================
float4 PS_ProcessGaussianH(VS_OUTPUT_POST IN) : COLOR
{
float sHeight = ScreenSize.x * ScreenSize.w;
float2 fvTexelSize = float2(ScreenSize.y, 1.0 / sHeight);
float px = fvTexelSize.x;
float py = fvTexelSize.y;
float4 color = 0.0;
if ( gauss_blur==1 )
{
color = tex2D(SamplerColor2, IN.txcoord.xy) * sampleWeights_1[0];
for(int i = 1; i < 3; ++i) {
color += tex2D(SamplerColor2, IN.txcoord.xy + float2(sampleOffsets_1*px, 0.0)) * sampleWeights_1;
color += tex2D(SamplerColor2, IN.txcoord.xy - float2(sampleOffsets_1*px, 0.0)) * sampleWeights_1;
}
}
if ( gauss_blur==2 )
{
color = tex2D(SamplerColor2, IN.txcoord.xy) * sampleWeights_2[0];
for(int i = 1; i < 5; ++i) {
color += tex2D(SamplerColor2, IN.txcoord.xy + float2(sampleOffsets_2*px, 0.0)) * sampleWeights_2;
color += tex2D(SamplerColor2, IN.txcoord.xy - float2(sampleOffsets_2*px, 0.0)) * sampleWeights_2;
}
}
if ( gauss_blur==3 )
{
color = tex2D(SamplerColor2, IN.txcoord.xy) * sampleWeights_3[0];
for(int i = 1; i < 6; ++i) {
color += tex2D(SamplerColor2, IN.txcoord.xy + float2(sampleOffsets_3*px, 0.0)) * sampleWeights_3;
color += tex2D(SamplerColor2, IN.txcoord.xy - float2(sampleOffsets_3[i]*px, 0.0)) * sampleWeights_3[i];
}
}
color.w = 1.0f;
return color;
}
float4 PS_ProcessGaussianV(VS_OUTPUT_POST IN) : COLOR
{
float sHeight = ScreenSize.x * ScreenSize.w;
float2 fvTexelSize = float2(ScreenSize.y, 1.0 / sHeight);
float px = fvTexelSize.x;
float py = fvTexelSize.y;
float4 color = 0.0;
if ( gauss_blur==1 )
{
color = tex2D(SamplerColor2, IN.txcoord.xy) * sampleWeights_1[0];
for(int i = 1; i < 3; ++i) {
color += tex2D(SamplerColor2, IN.txcoord.xy + float2(0.0, sampleOffsets_1[i]*py)) * sampleWeights_1[i];
color += tex2D(SamplerColor2, IN.txcoord.xy - float2(0.0, sampleOffsets_1[i]*py)) * sampleWeights_1[i];
}
}
if ( gauss_blur==2 )
{
color = tex2D(SamplerColor2, IN.txcoord.xy) * sampleWeights_2[0];
for(int i = 1; i < 5; ++i) {
color += tex2D(SamplerColor2, IN.txcoord.xy + float2(0.0, sampleOffsets_2[i]*py)) * sampleWeights_2[i];
color += tex2D(SamplerColor2, IN.txcoord.xy - float2(0.0, sampleOffsets_2[i]*py)) * sampleWeights_2[i];
}
}
if ( gauss_blur==3 )
{
color = tex2D(SamplerColor2, IN.txcoord.xy) * sampleWeights_3[0];
for(int i = 1; i < 6; ++i) {
color += tex2D(SamplerColor2, IN.txcoord.xy + float2(0.0, sampleOffsets_3[i]*py)) * sampleWeights_3[i];
color += tex2D(SamplerColor2, IN.txcoord.xy - float2(0.0, sampleOffsets_3[i]*py)) * sampleWeights_3[i];
}
}
color.w = 1.0f;
return color;
}
float4 PS_ProcessSoftLight(VS_OUTPUT_POST IN) : COLOR
{
float4 color = 0.0;
float4 baseC = tex2D(SamplerColor, IN.txcoord.xy);
float4 blendC = tex2D(SamplerColor2, IN.txcoord.xy);
float3 base = baseC.xyz;
float3 blend = blendC.xyz;
color.xyz = softlight( base, blend, sl_mix_set );
color.w = 1.0f;
return color;
}
float4 PS_ProcessGaussBloom(VS_OUTPUT_POST IN) : COLOR
{
float4 scrcolor = 0.0;
float4 color = 0.0;
float3 luma = float3(0.2125, 0.7154, 0.0721);
float pixluma = 0.0;
float4 baseC = tex2D(SamplerColor, IN.txcoord.xy);
float4 blendC = tex2D(SamplerColor2, IN.txcoord.xy);
float3 base = baseC.xyz;
float3 blend = blendC.xyz;
scrcolor.xyz = screen( base, blend );
//Bloom on luma
if (lumabloom==true)
{
if (lumasource==1) pixluma = dot( base, luma );
if (lumasource==2) pixluma = dot( blend, luma );
if (lumasource==3) pixluma = dot( scrcolor, luma );
color.xyz = lerp( base.xyz, scrcolor.xyz, gauss_bloom * pixluma );
};
if (lumabloom==false)
{
color.xyz = lerp( base.xyz, scrcolor.xyz, gauss_bloom );
};
float3 lumCoeff = float3(0.212656, 0.715158, 0.072186);
color.a = dot(lumCoeff, color.rgb);
float Curves_contrast_blend = lerp(ContrastCurveExt, ContrastCurveInt, EInteriorFactor);
Curves_contrast_blend *= (C_CONTRASTCURVES)? 1:0;
float x = color.a - 0.5;
x /= ((abs(x)*1.25) + 0.375 ) + 0.5;
color.rgb += (x - color.a) * Curves_contrast_blend;
color.w = 1.0f;
return color;
}
// COLOR CORRECTION
float4 PS_Process_Filter (VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
float4 res;
float4 coord = 0.0;
coord.xy = IN.txcoord.xy;
float4 original = tex2Dlod (SamplerColor, coord);
#if USE_K_FILTER == 0
return original;
#elif USE_K_FILTER == 1
if (enable_c_correction == false) return original;
float k_brightness = lerp (k_brightness_ext_night, k_brightness_ext_day, ENightDayFactor);
float noise_mix_curve = lerp (noise_mix_curve_ext_night, noise_mix_curve_ext_day, ENightDayFactor);
if (EInteriorFactor)
{
k_brightness = lerp (k_brightness_int_night, k_brightness_int_day, ENightDayFactor);
noise_mix_curve = lerp (noise_mix_curve_int_night, noise_mix_curve_int_day, ENightDayFactor);
};
float3 gray_filter = float3 (0.5285, 0.515, 0.515);
float clamp_low = 0.000005;
float clamp_high = 15.25;
float additive_noise_factor = 0.0075; // More ANF = more noise. Comment this line to disable the B&W filter entirely
float multiplicative_noise_min = -0.45;
float multiplicative_noise_max = -0.45;
// Black-white filter
// original.xyz = dot (original.xyz, gray_filter.xyz); // MIDHRAS: Comment this line to regain colour but keep TV noise
// Scale
original.xyz *= k_brightness;
// Limit
original.xyz = clamp (original.xyz, clamp_low, clamp_high);
// Noise
coord.xy = IN.txcoord.xy * ScreenSize.y * 4000.0;
coord.y += frac (Timer.x * 140000.0);
float4 noise_big = tex2D (SamplerNoise, coord);
float mix_fact = noise_big.x;
mix_fact = saturate ((mix_fact - 0.5) * 5.0);
coord.xy = IN.txcoord.xy * ScreenSize.x * 0.008;
coord.x += frac ((noise_big.y) * frac (Timer.x * 100000.0) * 1.3);
coord.y += frac (Timer.x * 160000.0);
float4 noise_color = tex2D (SamplerNoise, coord);
noise_color.w = lerp (noise_color.x, noise_color.y, mix_fact);
// Mix gray with noise
mix_fact = dot (original.xyz, 2.133);
mix_fact = pow (saturate (noise_mix_multiplier * mix_fact), noise_mix_curve);
noise_color.x = noise_color.w * additive_noise_factor;
noise_color.w = lerp (multiplicative_noise_min, multiplicative_noise_max, noise_color.w);
if (enable_k_blackness == true)
{
res.xyz = lerp (original.xyz * noise_color.w + noise_color.x, original.xyz, mix_fact);
}
if (enable_k_blackness == false)
{
res.xyz = original.rgb;
}
res.w = 1.0;
// Color Correction
if (enable_cc==true)
{
res.rgb=res.rgb+brightnessCorrection;
float contrastCorrection1=lerp(contrastCorrection,0,res.rgb);
res.rgb=(res.rgb-0.5)*(contrastCorrection1+1.0)+0.5;
float3 lumCoeff = float3(0.2125, 0.7154, 0.0721);
float luminance = dot(res,lumCoeff);
res = lerp(luminance, res, saturationCorrection);
float3 color = res.rgb;
float vContrast1 = lerp(vContrast, 1, color.rgb);
float4 res2=PP2(res,
vBrightness, // brightness
vContrast1, // contrast
vSaturation, // saturation
vTonemapping, // toneMapp
vTonemappingWhite);
float4 ov=Overlay(res,res2);
res=lerp(res,ov,vOverlay2);
float3 color3 = saturate(res.rgb);
color3 = color3 + (1 / 2.0 - 0.5) * (1.0 - color3);
color3 = saturate(color3);
res.rgb = pow(1.0 * color3, 1.0 / MidGamma);
float contrastCorrection2=lerp(vContrastFix,0,res.rgb);
res.rgb=(res.rgb-0.5)*(contrastCorrection2+1.0)+0.5;
}
return res;
#endif
}
float LumaDepth(float d, float n, float f)
{
return (2.0 * n)/(f + n - d * (f - n));
}
#define CoefLuma float3(0.2126, 0.7152, 0.0722)
#define px ScreenSize.y
#define sHeight ScreenSize.x * ScreenSize.w
#define py 1.0 / sHeight
float4 PS_SFXSharpen(VS_OUTPUT_POST IN, float2 vPos : VPOS, float2 tex : TEXCOORD0) : COLOR
{
float2 texcoord = IN.txcoord.xy;
float4 res;
res = tex2D(SamplerColor, texcoord);
float4 original = tex2D(SamplerColor, IN.txcoord.xy);
#if USE_DEPTHSHARPEN == 0
return original;
#elif USE_DEPTHSHARPEN == 1
if (ENABLE_SHARPENING==false) return original;
float3 ori = tex2D(SamplerColor, texcoord).rgb;
float3 sharp_strength_luma = (CoefLuma * fSharpStrength);
float3 blur_ori;
float Depth = tex2D(SamplerDepth, texcoord.xy ).x;
float linDepthFrom = LumaDepth(Depth, 0.5f, fFromDepth);
// Pattern 1 -- A (fast) 7 tap gaussian using only 2+1 texture fetches.
if (CHOOSE_BLUR==1)
{
blur_ori = tex2D(SamplerColor, texcoord + (float2(px,py) / 3.0) * fOffsetBias).rgb;
blur_ori += tex2D(SamplerColor, texcoord + (float2(-px,-py) / 3.0) * fOffsetBias).rgb;
blur_ori /= 2;
sharp_strength_luma *= 1.5;
}
// -- Pattern 2 -- A 9 tap gaussian using 4+1 texture fetches.
else if (CHOOSE_BLUR==2)
{
blur_ori = tex2D(SamplerColor, texcoord + float2(px,-py) * 0.5 * fOffsetBias).rgb;
blur_ori += tex2D(SamplerColor, texcoord + float2(-px,-py) * 0.5 * fOffsetBias).rgb;
blur_ori += tex2D(SamplerColor, texcoord + float2(px,py) * 0.5 * fOffsetBias).rgb;
blur_ori += tex2D(SamplerColor, texcoord + float2(-px,py) * 0.5 * fOffsetBias).rgb;
blur_ori *= 0.25;
}
// -- Pattern 3 -- An experimental 17 tap gaussian using 4+1 texture fetches.
else if (CHOOSE_BLUR==3)
{
blur_ori = tex2D(SamplerColor, texcoord + float2(0.4*px,-1.2*py)* fOffsetBias).rgb;
blur_ori += tex2D(SamplerColor, texcoord + float2(-1.2*px,-0.4*py) * fOffsetBias).rgb;
blur_ori += tex2D(SamplerColor, texcoord + float2(1.2*px,0.4*py) * fOffsetBias).rgb;
blur_ori += tex2D(SamplerColor, texcoord + float2(-0.4*px,1.2*py) * fOffsetBias).rgb;
blur_ori *= 0.25;
sharp_strength_luma *= 0.51;
}
// -- Pattern 4 -- A 9 tap high pass (pyramid filter) using 4+1 texture fetches.
else if (CHOOSE_BLUR==4)
{
blur_ori = tex2D(SamplerColor, texcoord + float2(0.5 * px,-py * fOffsetBias)).rgb;
blur_ori += tex2D(SamplerColor, texcoord + float2(fOffsetBias * -px,0.5 * -py)).rgb;
blur_ori += tex2D(SamplerColor, texcoord + float2(fOffsetBias * px,0.5 * py)).rgb;
blur_ori += tex2D(SamplerColor, texcoord + float2(0.5 * -px,py * fOffsetBias)).rgb;
blur_ori /= 4.0;
sharp_strength_luma *= 0.666;
}
float3 sharp = ori - blur_ori;
float4 sharp_strength_luma_clamp = float4(sharp_strength_luma * (0.5 / fSharpClamp),0.5);
float sharp_luma = saturate(dot(float4(sharp,1.0), sharp_strength_luma_clamp));
sharp_luma = (fSharpClamp * 2.0) * sharp_luma - fSharpClamp;
if (ENABLE_DEPTH==true) sharp_luma = sharp_luma * (1.0f - linDepthFrom);
res.xyz = ori + sharp_luma;
if (SHOW_EDGES==true) res = sharp_luma;
return saturate(res);
#endif
}
// BLURRING
float4 PS_Process_Blurring (VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
float4 res;
float4 coord = 0.0;
coord.xy = IN.txcoord.xy;
coord.w = 0.0;
float4 original = tex2Dlod (SamplerColor, coord);
#if USE_BLURRING == 0
return original;
#elif USE_BLURRING == 1
if (enable_blurring == false) return original;
if (use_h_blur == false)
{
float2 offset[16] =
{
float2 (1.0, 1.0),
float2 (-1.0, -1.0),
float2 (-1.0, 1.0),
float2 (1.0, -1.0),
float2 (1.0, 0.0),
float2 (-1.0, 0.0),
float2 (0.0, 1.0),
float2 (0.0, -1.0),
float2 (1.41, 0.0),
float2 (-1.41, 0.0),
float2 (0.0, 1.41),
float2 (0.0, -1.41),
float2 (1.41, 1.41),
float2 (-1.41, -1.41),
float2 (-1.41, 1.41),
float2 (1.41, -1.41)
};
int i = 0;
float4 tcol = original;
float inv_screen_size = 1.0 / ScreenSize;
for (i = 0; i < 16; i ++)
{
float2 tdir = offset[i].xy;
coord.xy = IN.txcoord.xy + tdir.xy * inv_screen_size * blur_range;
float4 ct = tex2Dlod (SamplerColor, coord);
tcol += ct;
}
tcol *= 0.05882353;
res.xyz = tcol.xyz;
}
if (use_h_blur == true)
{
int i = 0;
float4 tcol = 0.0;
float2 inv_screen_size = ScreenSize.y;
float offset = -2.0;
for (i = 0; i < 5; i ++)
{
coord.x = IN.txcoord.x + offset * inv_screen_size * blur_range;
float4 ct = tex2Dlod (SamplerColor, coord);
tcol += ct;
offset += 1.0;
}
res.xyz = tcol.xyz * 0.2;
}
res.w = 1.0;
return res;
#endif
}
// SHARPENING
float4 PS_Process_Sharpening (VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
float4 res;
float4 coord = 0.0;
coord.xy = IN.txcoord.xy;
coord.w = 0.0;
float4 original = tex2Dlod (SamplerColor, coord);
#if USE_SHARPENING == 0
return original;
#elif USE_SHARPENING == 1
if (enable_sharpening == false) return original;
float sharp_amount = lerp (lerp (sharp_amount_night, sharp_amount_day, ENightDayFactor), sharp_amount_int, EInteriorFactor);
float2 offset[8] =
{
float2 (1.0, 1.0),
float2 (-1.0, -1.0),
float2 (-1.0, 1.0),
float2 (1.0, -1.0),
float2 (1.41, 0.0),
float2 (-1.41, 0.0),
float2 (0.0, 1.41),
float2 (0.0, -1.41)
};
int i = 0;
float4 tcol = original;
float inv_screen_size = 1.0 / ScreenSize;
#if SHARPENING_QUALITY == 1
for (i = 0; i < 4; i ++)
#elif SHARPENING_QUALITY == 2
for (i = 0; i < 8; i ++)
#endif
{
float2 tdir = offset[i].xy;
coord.xy = IN.txcoord.xy + tdir.xy * inv_screen_size * sharp_range;
float4 ct = tex2Dlod (SamplerColor, coord);
tcol += ct;
}
#if SHARPENING_QUALITY == 1
tcol *= 0.2;
#elif SHARPENING_QUALITY == 2
tcol *= 0.1111;
#endif
// Sharp by color
if (use_sharp_by_color == true)
{
res = original * (1.0 + ((original - tcol) * sharp_amount));
}
// Sharp by gray
if (use_sharp_by_color == false)
{
float diff_fact = dot ((original.xyz - tcol.xyz), 0.333);
res = original * (1.0 + diff_fact * sharp_amount);
}
// Less sharpening for bright pixels
float r_gray = original.z;
r_gray = pow (r_gray, 3.0);
res = lerp (res, original, saturate (r_gray));
res.w = 1.0;
return res;
#endif
}
// COLOR SHIFT
float4 PS_Process_ColorShift (VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
float4 res;
float4 coord = 0.0;
coord.xy = IN.txcoord.xy;
coord.w = 0.0;
float4 original = tex2Dlod (SamplerColor, coord);
#if USE_COLORSHIFT == 0
return original;
#elif USE_COLORSHIFT == 1
if (enable_color_shift == false) return original;
int i = 0;
float4 tcol = original;
float2 inv_screen_size = 1.0 / ScreenSize.x;
inv_screen_size.y = inv_screen_size.y / ScreenSize.z;
coord.xy = IN.txcoord.xy;
original = tex2Dlod (SamplerColor, coord);
res.y = original.y;
coord.xy = IN.txcoord.xy;
coord.y -= inv_screen_size * color_shift_range;
original = tex2Dlod (SamplerColor, coord);
res.x = original.x;
coord.xy = IN.txcoord.xy;
coord.y += inv_screen_size * color_shift_range;
original = tex2Dlod (SamplerColor, coord);
res.z = original.z;
res.w = 1.0;
return res;
#endif
}
// CONTRAST
float4 PS_Process_Contrast (VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
float4 res;
float3 original = tex2D (SamplerColor, IN.txcoord.xy);
#if USE_CONTRAST == 0
res.rgb = original.rgb;
res.w = 1.0;
return res;
#elif USE_CONTRAST == 1
if (enable_contrast == false)
{
res.rgb = original.rgb;
res.w = 1.0;
return res;
}
float contrast_curve = lerp (contrast_ext_night, contrast_ext_day, ENightDayFactor);
if (EInteriorFactor)
{
contrast_curve = lerp (contrast_int_night, contrast_int_day, ENightDayFactor);
};
float3 luma_coef = float3 (0.212656, 0.715158, 0.072186); // Calculate luma with these values
float luma = dot (luma_coef, original.rgb);
float3 chroma = original.rgb - luma;
float curves_contrast_blend = contrast_curve;
float PI = 3.1415926535897932384626433832795;
float x = luma; // If the curve should be applied to Luma
x = x - 0.5;
x = x / ((abs (x) * 1.25) + 0.375) + 0.5;
x = lerp (luma, x, curves_contrast_blend); // If the curve should be applied to both Luma and Chroma
res.rgb = x + chroma; // Blend by curves_contrast
res.w = 1.0;
return res;
#endif
}
// Paint
float4 PS_Paint(VS_OUTPUT_POST IN) : COLOR
{
float4 res = tex2D(SamplerColor, IN.txcoord.xy);
float2 pixelSize=ScreenSize.y;
pixelSize.y*=ScreenSize.z;
int PaintRadius = radiuspaint;
if (enable_paint==true)
{
float Intensitycount[10];
float3 color[10];
int MaxPaintRadius = 20;//same as UImax in gui.
for(int k=0 ; k < (MaxPaintRadius * 2 + 1) && k < (PaintRadius * 2 + 1); k++)
{
for(int j=0 ; j < (MaxPaintRadius * 2 + 1) && j < (PaintRadius * 2 + 1); j++)
{
float2 tex;
tex.x = IN.txcoord.x + pixelSize.x * (k - PaintRadius );
tex.y = IN.txcoord.y + pixelSize.y * (j - PaintRadius );
float3 c = tex2Dlod(SamplerColor, float4(tex, 0, 0));
int lum = dot(c, float3(0.212, 0.716, 0.072)) * 9;
Intensitycount[0] = ( lum == 0) ? Intensitycount[0] + 1 : Intensitycount[0];
Intensitycount[1] = ( lum == 1) ? Intensitycount[1] + 1 : Intensitycount[1];
Intensitycount[2] = ( lum == 2) ? Intensitycount[2] + 1 : Intensitycount[2];
Intensitycount[3] = ( lum == 3) ? Intensitycount[3] + 1 : Intensitycount[3];
Intensitycount[4] = ( lum == 4) ? Intensitycount[4] + 1 : Intensitycount[4];
Intensitycount[5] = ( lum == 5) ? Intensitycount[5] + 1 : Intensitycount[5];
Intensitycount[6] = ( lum == 6) ? Intensitycount[6] + 1 : Intensitycount[6];
Intensitycount[7] = ( lum == 7) ? Intensitycount[7] + 1 : Intensitycount[7];
Intensitycount[8] = ( lum == 8) ? Intensitycount[8] + 1 : Intensitycount[8];
Intensitycount[9] = ( lum == 9) ? Intensitycount[9] + 1 : Intensitycount[9];
color[0] = ( lum == 0) ? color[0] + c : color[0];
color[1] = ( lum == 1) ? color[1] + c : color[1];
color[2] = ( lum == 2) ? color[2] + c : color[2];
color[3] = ( lum == 3) ? color[3] + c : color[3];
color[4] = ( lum == 4) ? color[4] + c : color[4];
color[5] = ( lum == 5) ? color[5] + c : color[5];
color[6] = ( lum == 6) ? color[6] + c : color[6];
color[7] = ( lum == 7) ? color[7] + c : color[7];
color[8] = ( lum == 8) ? color[8] + c : color[8];
color[9] = ( lum == 9) ? color[9] + c : color[9];
}
}
int Maxint = 0;
int Maxcount = 0;
for(int i = 0; i < 10; i++)
{
if(Intensitycount[i] > Maxcount)
{
Maxcount = Intensitycount[i];
Maxint = i;
}
}
res.xyz = color[Maxint] / Maxcount;
res.w = 1;
}
return res;
}
float4 PS_Process_AfterFX (VS_OUTPUT_POST IN, float2 vPos : VPOS, float2 tex : TEXCOORD0) : COLOR
{
float4 res;
float3 original = tex2D (SamplerColor, IN.txcoord.xy);
// VIGNETTE
#if USE_VIGNETTE == 0
res.xyz = original.xyz;
#elif USE_VIGNETTE == 1
if (enable_vignette == false)
{
res.xyz = original.xyz;
}
if (enable_vignette == true)
{
float vignette_amount = lerp (lerp (vignette_amount_night, vignette_amount_day, ENightDayFactor), vignette_amount_int, EInteriorFactor);
float vignette_radius = lerp (lerp (vignette_radius_night, vignette_radius_day, ENightDayFactor), vignette_radius_int, EInteriorFactor);
float vignette_curve = lerp (lerp (vignette_curve_night, vignette_curve_day, ENightDayFactor), vignette_curve_int, EInteriorFactor);
float2 uv = (IN.txcoord.xy - 0.5) * vignette_radius;
float vignette = saturate (dot (uv.xy, uv.xy));
vignette = pow (vignette, vignette_curve);
res.xyz = lerp (original.xyz, vignette_color, vignette * vignette_amount);
}
#endif
// NOISE
#if USE_NOISE == 1
if (enable_noise == true)
{
float GrainTimerSeed = Timer.x * GrainMotion;
float2 GrainTexCoordSeed = IN.txcoord.xy * 1.0;
float Interpolate = dot( res.xyz, 0.33333333 );
//Generate grain seeds
float2 GrainSeed1 = GrainTexCoordSeed + float2( 0.0, GrainTimerSeed );
float2 GrainSeed2 = GrainTexCoordSeed + float2( GrainTimerSeed, 0.0 );
float2 GrainSeed3 = GrainTexCoordSeed + float2( GrainTimerSeed, GrainTimerSeed );
//Generate pseudo random noise
float GrainNoise1 = random( GrainSeed1 );
float GrainNoise2 = random( GrainSeed2 );
float GrainNoise3 = random( GrainSeed3 );
float GrainNoise4 = ( GrainNoise1 + GrainNoise2 + GrainNoise3 ) * 0.333333333;
//Combine results
float3 GrainNoise = float3( GrainNoise4, GrainNoise4, GrainNoise4 );
float3 GrainColor = float3( GrainNoise1, GrainNoise2, GrainNoise3 );
float3 Noise = ( lerp( GrainNoise, GrainColor, GrainSaturation ) * GrainIntensity ) - ( GrainIntensity * 0.5);
//Add noise to color
res.xyz += Noise.xyz;
//ShadowNoise
Noise = ( lerp( GrainNoise, GrainColor, GrainSatShadow ) * GrainIntensityShadow ) - ( GrainIntensityShadow * 0.5);
res.xyz = lerp( res.xyz + Noise.xyz, res.xyz, pow( Interpolate, noiseCurve ));
}
#endif
// DITHERING
#if USE_DITHERING == 1
if (enable_dithering == true)
{
float dither_bit = 8.0; // Number of bits per channel. Should be 8 for most monitors
float grid_position = frac (dot (IN.txcoord, (ScreenSize.x / dither_size)) + (0.5 / dither_size));
// Make some noise
float noise = frac (sin (dot (float4 (tex, -tex.yx), float4 (float2 (12.9898, 78.233), float2 (12.9898, 78.233) * acos (-1)))) * 43758.5453); // Pseudo random number generator
noise -= 0.5;
// Calculate how big the shift should be
float dither_shift = (noise) * (1.0 / (pow (2, dither_bit) - 1.0)); // Using noise to determine shift. The noise ahould vary between +- 0.5
// Shift the individual colors differently, thus making it even harder to see the dithering pattern
float3 dither_shift_RGB = float3 (dither_shift, dither_shift, dither_shift);
// Shift the color by dither_shift
res.xyz += lerp (2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position);
}
#endif
// BORDER
#if USE_BORDER == 1
if (enable_border == true)
{
float2 dist_from_center = abs (IN.txcoord.xy - 0.5);
bool2 screen_border = step (0.5 - (border_width / ScreenSize.x), dist_from_center);
res.xyz = (!dot (screen_border, 1.0)) ? res.xyz : 0.0;
}
#endif
// LETTERBOX
#if USE_LETTERBOX == 1
if (enable_letterbox == true)
{
float offset = letterbox_size * 0.01;
if (IN.txcoord.y <= offset || IN.txcoord.y >= (1.0 - offset)) res.xyzw = 0.0;
}
#endif
res.w = 1.0f;
return res;
}
//=================================================================================================================
// TECHNIQUES
//=================================================================================================================
technique PostProcess
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess();
PixelShader = compile ps_3_0 PS_Paint();
PixelShader = compile ps_3_0 PS_ProcessGaussianH();
DitherEnable=FALSE;
ZEnable=FALSE;
CullMode=NONE;
ALPHATESTENABLE=FALSE;
SEPARATEALPHABLENDENABLE=FALSE;
AlphaBlendEnable=FALSE;
StencilEnable=FALSE;
FogEnable=FALSE;
SRGBWRITEENABLE=FALSE;
}
}
technique PostProcess2
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess ();
PixelShader = compile ps_3_0 PS_Process_Filter ();
PixelShader = compile ps_3_0 PS_ProcessGaussianV();
DitherEnable = FALSE;
ZEnable = FALSE;
CullMode = NONE;
ALPHATESTENABLE = FALSE;
SEPARATEALPHABLENDENABLE = FALSE;
AlphaBlendEnable = FALSE;
StencilEnable = FALSE;
FogEnable = FALSE;
SRGBWRITEENABLE = FALSE;
}
}
technique PostProcess3
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess ();
PixelShader = compile ps_3_0 PS_SFXSharpen ();
PixelShader = compile ps_3_0 PS_ProcessSoftLight();
DitherEnable = FALSE;
ZEnable = FALSE;
CullMode = NONE;
ALPHATESTENABLE = FALSE;
SEPARATEALPHABLENDENABLE = FALSE;
AlphaBlendEnable = FALSE;
StencilEnable = FALSE;
FogEnable = FALSE;
SRGBWRITEENABLE = FALSE;
}
}
technique PostProcess4
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess ();
PixelShader = compile ps_3_0 PS_Process_Blurring ();
PixelShader = compile ps_3_0 PS_ProcessGaussianH();
DitherEnable = FALSE;
ZEnable = FALSE;
CullMode = NONE;
ALPHATESTENABLE = FALSE;
SEPARATEALPHABLENDENABLE = FALSE;
AlphaBlendEnable = FALSE;
StencilEnable = FALSE;
FogEnable = FALSE;
SRGBWRITEENABLE = FALSE;
}
}
technique PostProcess5
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess ();
PixelShader = compile ps_3_0 PS_Process_Sharpening ();
PixelShader = compile ps_3_0 PS_ProcessGaussianV();
DitherEnable = FALSE;
ZEnable = FALSE;
CullMode = NONE;
ALPHATESTENABLE = FALSE;
SEPARATEALPHABLENDENABLE = FALSE;
AlphaBlendEnable = FALSE;
StencilEnable = FALSE;
FogEnable = FALSE;
SRGBWRITEENABLE = FALSE;
}
}
technique PostProcess6
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess ();
PixelShader = compile ps_3_0 PS_Process_ColorShift ();
PixelShader = compile ps_3_0 PS_ProcessGaussBloom();
DitherEnable = FALSE;
ZEnable = FALSE;
CullMode = NONE;
ALPHATESTENABLE = FALSE;
SEPARATEALPHABLENDENABLE = FALSE;
AlphaBlendEnable = FALSE;
StencilEnable = FALSE;
FogEnable = FALSE;
SRGBWRITEENABLE = FALSE;
}
}
technique PostProcess7
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess ();
PixelShader = compile ps_3_0 PS_Process_Contrast ();
DitherEnable = FALSE;
ZEnable = FALSE;
CullMode = NONE;
ALPHATESTENABLE = FALSE;
SEPARATEALPHABLENDENABLE = FALSE;
AlphaBlendEnable = FALSE;
StencilEnable = FALSE;
FogEnable = FALSE;
SRGBWRITEENABLE = FALSE;
}
}
technique PostProcess8
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess ();
PixelShader = compile ps_3_0 PS_Process_AfterFX ();
DitherEnable = FALSE;
ZEnable = FALSE;
CullMode = NONE;
ALPHATESTENABLE = FALSE;
SEPARATEALPHABLENDENABLE = FALSE;
AlphaBlendEnable = FALSE;
StencilEnable = FALSE;
FogEnable = FALSE;
SRGBWRITEENABLE = FALSE;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Here is the second effect:
- /**
* SHADER ADDON
* Featuring: Gaussian blur passes for Photoshop: Soft Light and Screen blending techniques ( finest Contrast bloom )
* Effect is FPS heavy and subtle. Use as you see fit. Scaled for 1080 resolution. Higher resolutions and effect is minimal ( blur is pixel based ) and FPS hit bigger.
* LumaSharpen by CeeJay.dk & ZeroKing
* By prod80 - Serenity ENB
*/
/**
* ENBSeries
* visit http://enbdev.com for updates
* Copyright (c) 2007-2014 Boris Vorontsov
*/
//--------------------------//
// Internal parameters //
// Can be modified //
//--------------------------//
//////////////////
// DEFINES //
//////////////////
#define SharpMethod 4 //[1, 2, 3, 4] Comment out (add // in front) to disable sharpening pass and GUI for it
////////////////////
// CONTRAST BLOOM //
////////////////////
float sl_mix_set <
string UIName="Soft Light Intensity";
string UIWidget="Spinner";
float UIMin=0.0;
float UIMax=1.0;
float UIStep=0.001;
> = {0.275};
float gauss_bloom <
string UIName="Gaussian Bloom Intensity";
string UIWidget="Spinner";
float UIMin=0.0;
float UIMax=1.0;
float UIStep=0.001;
> = {0.550};
bool lumabloom <
string UIName="Luma based Bloom";
> = {true};
float lumasource <
string UIName="Luma Src 1_orig 2_softlight 3_blend";
string UIWidget="Spinner";
float UIMin=1;
float UIMax=3;
float UIStep=1;
> = {2};
float gauss_blur <
string UIName="Gaussian Blur Strength";
string UIWidget="Spinner";
float UIMin=1;
float UIMax=3;
float UIStep=1;
> = {2};
////////////////////
// LUMASHARPEN //
////////////////////
#ifdef SharpMethod
bool Section_Luma <
string UIName="------Lumasharpen-----------";
> = {false};
float sharp_strengthExt <
string UIName="LumaSharpen Strength Exterior";
string UIWidget="Spinner";
float UIMin=0.0;
float UIMax=5.0;
float UIStep=0.001;
> = {0.315};
float sharp_strengthInt <
string UIName="LumaSharpen Strength Interior";
string UIWidget="Spinner";
float UIMin=0.0;
float UIMax=5.0;
float UIStep=0.001;
> = {0.315};
float sharp_clampExt <
string UIName="LumaSharpen Clamp Exterior";
string UIWidget="Spinner";
float UIMin=0.0;
float UIMax=1.0;
float UIStep=0.001;
> = {0.017};
float sharp_clampInt <
string UIName="LumaSharpen Clamp Interior";
string UIWidget="Spinner";
float UIMin=0.0;
float UIMax=1.0;
float UIStep=0.001;
> = {0.017};
#endif
//////////////////
// CONTRAST //
//////////////////
bool Section_Contrast <
string UIName="------Contrast-----------";
> = {false};
bool C_CONTRASTCURVES <
string UIName = "Enable Contrast";
> = {false};
float ContrastCurveExt <
string UIName="Contrast - Exterior";
string UIWidget="Spinner";
float UIMin=-1.0;
float UIMax=1.0;
> = {0};
float ContrastCurveInt <
string UIName="Contrast - Interior";
string UIWidget="Spinner";
float UIMin=-1.0;
float UIMax=1.0;
> = {0};
////////////////////
// BLACK LEVELS //
////////////////////
bool Section_BLACKLEVEL <
string UIName="------Black Level-----------";
> = {false};
bool C_BLACKLEVEL <
string UIName = "Enable Black Level";
> = {false};
float BlackPointExt <
string UIName="Black Level - Exterior";
string UIWidget="Spinner";
float UIMin=0.0;
float UIMax=255.0;
> = {16};
float BlackPointInt <
string UIName="Black Level - Interior";
string UIWidget="Spinner";
float UIMin=0.0;
float UIMax=255.0;
> = {16};
float WhitePointExt <
string UIName="White Level - Exterior";
string UIWidget="Spinner";
float UIMin=0.0;
float UIMax=255.0;
> = {235};
float WhitePointInt <
string UIName="White Level - Interior";
string UIWidget="Spinner";
float UIMin=0.0;
float UIMax=255.0;
> = {235};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//--------------------------//
// External parameters //
// Do not modify //
//--------------------------//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Keyboard controlled temporary variables.
// Press and hold key 1,2,3...8 together with PageUp or PageDown to modify.
// By default all set to 1.0
float4 tempF1; //0,1,2,3
float4 tempF2; //5,6,7,8
float4 tempF3; //9,0
float4 Timer; //x=generic timer in range 0..1, period of 16777216 ms (4.6 hours), w=frame time elapsed (in seconds)
float4 ScreenSize; //x=Width, y=1/Width, z=ScreenScaleY, w=1/ScreenScaleY
float ENightDayFactor; //changes in range 0..1, 0 means that night time, 1 - day time
float EInteriorFactor; //changes 0 or 1. 0 means that exterior, 1 - interior
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////
// TEXTURES //
//////////////////
texture2D texOriginal;
texture2D texColor;
texture2D texNoise;
///////////////////
// SAMPLERS //
///////////////////
sampler2D SamplerColor = sampler_state
{
Texture = <texOriginal>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = NONE;
AddressU = Clamp;
AddressV = Clamp;
SRGBTexture=FALSE;
MaxMipLevel=0;
MipMapLodBias=0;
};
sampler2D SamplerColor2 = sampler_state
{
Texture = <texColor>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = NONE;
AddressU = Clamp;
AddressV = Clamp;
SRGBTexture=FALSE;
MaxMipLevel=0;
MipMapLodBias=0;
};
sampler2D SamplerNoise = sampler_state
{
Texture = <texNoise>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = NONE;
AddressU = Wrap;
AddressV = Wrap;
SRGBTexture=FALSE;
MaxMipLevel=0;
MipMapLodBias=0;
};
//////////////////
// STRUCTS //
//////////////////
struct VS_OUTPUT_POST
{
float4 vpos : POSITION;
float2 txcoord : TEXCOORD0;
};
struct VS_INPUT_POST
{
float3 pos : POSITION;
float2 txcoord : TEXCOORD0;
};
VS_OUTPUT_POST VS_PostProcess(VS_INPUT_POST IN)
{
VS_OUTPUT_POST OUT;
float4 pos=float4(IN.pos.x,IN.pos.y,IN.pos.z,1.0);
OUT.vpos=pos;
OUT.txcoord.xy=IN.txcoord.xy;
return OUT;
}
//////////////////
// HELPER FUNCS //
//////////////////
//GAUSSIAN WEIGHTS - Linear sampled for high performance
//9 tap reduced to 3 weights ( 17 pixels wide )
static const float sampleOffsets_1[3] = { 0.0, 1.137453814668, 3.013581103919 };
static const float sampleWeights_1[3] = { 0.441440131387, 0.277468870531, 0.001811063775 };
//17 tap reduced to 5 weights ( 33 pixels wide )
static const float sampleOffsets_2[5] = { 0.0, 1.263686497497, 3.083471450524, 5.022636787155, 7.005855649638 };
static const float sampleWeights_2[5] = { 0.330086281980, 0.318351147970, 0.016540813281, 0.000064880504, 0.000000017255 };
//21 tap reduced to 6 weights ( 41 pixels wide )
static const float sampleOffsets_3[6] = { 0.0, 1.452313744966, 3.390210239952, 5.331472958797, 7.277552900121, 9.229394260785 };
static const float sampleWeights_3[6] = { 0.142479385858, 0.244115579374, 0.131636577371, 0.043283482080, 0.008668409765, 0.001056258481 };
float3 softlight(float3 a, float3 b, float s)
{
float3 ret;
float3 b_x2 = 2.0 * b;
float3 a_b_x2 = a * b_x2;
float3 c1 = a_b_x2 + a * a - a * a_b_x2;
float3 c2 = sqrt(a) * ( b_x2 - 1.0 ) + 2.0 * a - a_b_x2;
ret = ( b >= 0.5 ) ? c1 : c2;
return lerp( a, ret, s );
}
float3 screen(float3 a, float3 b)
{
return (1.0f - (1.0f - a) * (1.0f - b));
}
//////////////////
// SHADERS //
//////////////////
float4 PS_ProcessGaussianH(VS_OUTPUT_POST IN) : COLOR
{
float sHeight = ScreenSize.x * ScreenSize.w;
float2 fvTexelSize = float2(ScreenSize.y, 1.0 / sHeight);
float px = fvTexelSize.x;
float py = fvTexelSize.y;
float4 color = 0.0;
if ( gauss_blur==1 )
{
color = tex2D(SamplerColor2, IN.txcoord.xy) * sampleWeights_1[0];
for(int i = 1; i < 3; ++i) {
color += tex2D(SamplerColor2, IN.txcoord.xy + float2(sampleOffsets_1[i]*px, 0.0)) * sampleWeights_1[i];
color += tex2D(SamplerColor2, IN.txcoord.xy - float2(sampleOffsets_1[i]*px, 0.0)) * sampleWeights_1[i];
}
}
if ( gauss_blur==2 )
{
color = tex2D(SamplerColor2, IN.txcoord.xy) * sampleWeights_2[0];
for(int i = 1; i < 5; ++i) {
color += tex2D(SamplerColor2, IN.txcoord.xy + float2(sampleOffsets_2[i]*px, 0.0)) * sampleWeights_2[i];
color += tex2D(SamplerColor2, IN.txcoord.xy - float2(sampleOffsets_2[i]*px, 0.0)) * sampleWeights_2[i];
}
}
if ( gauss_blur==3 )
{
color = tex2D(SamplerColor2, IN.txcoord.xy) * sampleWeights_3[0];
for(int i = 1; i < 6; ++i) {
color += tex2D(SamplerColor2, IN.txcoord.xy + float2(sampleOffsets_3[i]*px, 0.0)) * sampleWeights_3[i];
color += tex2D(SamplerColor2, IN.txcoord.xy - float2(sampleOffsets_3[i]*px, 0.0)) * sampleWeights_3[i];
}
}
color.w = 1.0f;
return color;
}
float4 PS_ProcessGaussianV(VS_OUTPUT_POST IN) : COLOR
{
float sHeight = ScreenSize.x * ScreenSize.w;
float2 fvTexelSize = float2(ScreenSize.y, 1.0 / sHeight);
float px = fvTexelSize.x;
float py = fvTexelSize.y;
float4 color = 0.0;
if ( gauss_blur==1 )
{
color = tex2D(SamplerColor2, IN.txcoord.xy) * sampleWeights_1[0];
for(int i = 1; i < 3; ++i) {
color += tex2D(SamplerColor2, IN.txcoord.xy + float2(0.0, sampleOffsets_1[i]*py)) * sampleWeights_1[i];
color += tex2D(SamplerColor2, IN.txcoord.xy - float2(0.0, sampleOffsets_1[i]*py)) * sampleWeights_1[i];
}
}
if ( gauss_blur==2 )
{
color = tex2D(SamplerColor2, IN.txcoord.xy) * sampleWeights_2[0];
for(int i = 1; i < 5; ++i) {
color += tex2D(SamplerColor2, IN.txcoord.xy + float2(0.0, sampleOffsets_2[i]*py)) * sampleWeights_2[i];
color += tex2D(SamplerColor2, IN.txcoord.xy - float2(0.0, sampleOffsets_2[i]*py)) * sampleWeights_2[i];
}
}
if ( gauss_blur==3 )
{
color = tex2D(SamplerColor2, IN.txcoord.xy) * sampleWeights_3[0];
for(int i = 1; i < 6; ++i) {
color += tex2D(SamplerColor2, IN.txcoord.xy + float2(0.0, sampleOffsets_3[i]*py)) * sampleWeights_3[i];
color += tex2D(SamplerColor2, IN.txcoord.xy - float2(0.0, sampleOffsets_3[i]*py)) * sampleWeights_3[i];
}
}
color.w = 1.0f;
return color;
}
float4 PS_ProcessSoftLight(VS_OUTPUT_POST IN) : COLOR
{
float4 color = 0.0;
float4 baseC = tex2D(SamplerColor, IN.txcoord.xy);
float4 blendC = tex2D(SamplerColor2, IN.txcoord.xy);
float3 base = baseC.xyz;
float3 blend = blendC.xyz;
color.xyz = softlight( base, blend, sl_mix_set );
color.w = 1.0f;
return color;
}
float4 PS_ProcessGaussBloom(VS_OUTPUT_POST IN) : COLOR
{
float4 scrcolor = 0.0;
float4 color = 0.0;
float3 luma = float3(0.2125, 0.7154, 0.0721);
float pixluma = 0.0;
float4 baseC = tex2D(SamplerColor, IN.txcoord.xy);
float4 blendC = tex2D(SamplerColor2, IN.txcoord.xy);
float3 base = baseC.xyz;
float3 blend = blendC.xyz;
scrcolor.xyz = screen( base, blend );
//Bloom on luma
if (lumabloom==true)
{
if (lumasource==1) pixluma = dot( base, luma );
if (lumasource==2) pixluma = dot( blend, luma );
if (lumasource==3) pixluma = dot( scrcolor, luma );
color.xyz = lerp( base.xyz, scrcolor.xyz, gauss_bloom * pixluma );
};
if (lumabloom==false)
{
color.xyz = lerp( base.xyz, scrcolor.xyz, gauss_bloom );
};
float3 lumCoeff = float3(0.212656, 0.715158, 0.072186);
color.a = dot(lumCoeff, color.rgb);
float Curves_contrast_blend = lerp(ContrastCurveExt, ContrastCurveInt, EInteriorFactor);
Curves_contrast_blend *= (C_CONTRASTCURVES)? 1:0;
float x = color.a - 0.5;
x /= ((abs(x)*1.25) + 0.375 ) + 0.5;
color.rgb += (x - color.a) * Curves_contrast_blend;
color.w = 1.0f;
return color;
}
#ifdef SharpMethod
float4 PS_ProcessLumaSharpen(VS_OUTPUT_POST IN, float2 vPos : VPOS, float2 tex : TEXCOORD0) : COLOR
{
float2 coord = IN.txcoord.xy;
float sHeight = ScreenSize.x * ScreenSize.w;
float2 fvTexelSize = float2(ScreenSize.y, 1.0 / sHeight);
float px = fvTexelSize.x;
float py = fvTexelSize.y;
// Bias value
float offset_bias = 1.0;
float sharp_strength = sharp_strengthExt;
float sharp_clamp = sharp_clampExt;
if (EInteriorFactor)
{
sharp_strength = sharp_strengthInt;
sharp_clamp = sharp_clampInt;
};
#define sharp_strength_luma (CoefLuma * sharp_strength)
#define CoefLuma float4(0.2126, 0.7152, 0.0722, 0)
half4 ori = tex2D(SamplerColor2, coord.xy);
[branch] if (any(frac(ori.rgb)))
{
#if SharpMethod == 1
// -- Gaussian filter --
// [ 2/9, 4/9, ] [ 1 , 2 , ]
// [ 4/9, 8/9, 4/9] = [ 2 , 4 , 2 ]
// [ , 2/9, 2/9] [ , 2 , 1 ]
half4 blur_ori = tex2Dlod(SamplerColor2, float4(tex,tex) + float4(-px,py,-px,py) / 3 * offset_bias); // North West
blur_ori += tex2Dlod(SamplerColor2, float4(tex,tex) + float4(px,-py,px,-py) / 3 * offset_bias); // South East
//Divide by the number of texture fetches
blur_ori /= 2;
#endif
// -- Pattern 2 -- A 9 tap gaussian using 4+1 texture fetches.
#if SharpMethod == 2
// -- Gaussian filter --
// [ .25, .50, .25] [ 1 , 2 , 1 ]
// [ .50, 1, .50] = [ 2 , 4 , 2 ]
// [ .25, .50, .25] [ 1 , 2 , 1 ]
half4 blur_ori = tex2Dlod(SamplerColor2, float4(tex,tex) + float4(-px,py,-px,py) * 0.5 * offset_bias); // North West
blur_ori += tex2Dlod(SamplerColor2, float4(tex,tex) + float4(px,-py,px,-py) * 0.5 * offset_bias); // South East
if (any((blur_ori.rgb / 2) - ori.rgb))
{
blur_ori += tex2Dlod(SamplerColor2, float4(tex,tex) + float4(-px,-py,-px,-py) * 0.5 * offset_bias); // South West
blur_ori += tex2Dlod(SamplerColor2, float4(tex,tex) + float4(px,py,px,py) * 0.5 * offset_bias); // North East
//Divide by the number of texture fetches
blur_ori *= 0.25;;
}
//Divide by the number of texture fetches
blur_ori *= 0.25;;
#endif
// -- Pattern 3 -- An experimental 17 tap gaussian using 4+1 texture fetches.
#if SharpMethod == 3
// -- Gaussian filter --
// [ , 4 , 6 , , ]
// [ ,16 ,24 ,16 , 4 ]
// [ 6 ,24 ,50 ,24 , 6 ]
// [ 4 ,16 ,24 ,16 , ]
// [ , , 6 , 4 , ]
half4 blur_ori = tex2Dlod(SamplerColor2, float4(tex,tex) + float4(-0.4*px,1.2*py,-0.4*px,1.2*py) * offset_bias); // North North West
blur_ori += tex2Dlod(SamplerColor2, float4(tex,tex) + float4(0.4*px,-1.2*py,0.4*px,-1.2*py) * offset_bias); // South South East
blur_ori += tex2Dlod(SamplerColor2, float4(tex,tex) + float4(1.2*px,0.4*py,0,0) * offset_bias); // East North East
blur_ori += tex2Dlod(SamplerColor2, float4(tex,tex) + float4(-1.2*px,-0.4*py,0,0) * offset_bias); // West South West
blur_ori += ori; // Probably not needed. Only serves to lessen the effect.
blur_ori /= 5; //Divide by the number of texture fetches
#endif
// -- Pattern 4 -- A 9 tap high pass using 4+1 texture fetches.
#if SharpMethod == 4
// -- Gaussian filter --
// [ .50, .50, .50] [ 1 , 1 , 1 ]
// [ .50, , .50] = [ 1 , , 1 ]
// [ .50, .50, .50] [ 1 , 1 , 1 ]
half4 blur_ori = tex2Dlod(SamplerColor2, float4(tex,tex) + float4(0.5 * -px,py,0.5 * -px,py) * offset_bias); // North North West
blur_ori += tex2Dlod(SamplerColor2, float4(tex,tex) + float4(0.5 * px,-py,0.5 * px,-py)); // South South East
blur_ori += tex2Dlod(SamplerColor2, float4(tex,tex) + float4(-px,0.5 * -py,-px,0.5 * -py)); // West South West
blur_ori += tex2Dlod(SamplerColor2, float4(tex,tex) + float4(px,0.5 * py,px,0.5 * py) * offset_bias); // East North East
blur_ori += (2 * ori); // Probably not needed. Only serves to lessen the effect.
blur_ori /= 6; //Divide by the number of texture fetches
#endif
// -- Calculate the sharpening --
half sharp = ori - blur_ori;
// -- Adjust strength of the sharpening --
sharp = dot(sharp, sharp_strength_luma);
// -- Clamping the maximum amount of sharpening to prevent halo artifacts --
sharp = clamp(sharp, -sharp_clamp, sharp_clamp);
// -- Combining the values to get the final sharpened pixel --
ori = ori + sharp;
}
float Levels_black_point = lerp(BlackPointExt, BlackPointInt, EInteriorFactor);
float Levels_white_point = lerp(WhitePointExt, WhitePointInt, EInteriorFactor);
if(C_BLACKLEVEL)
ori.rgb = (ori.rgb * 255 - Levels_black_point) / (Levels_white_point - Levels_black_point);
return ori;
}
#endif
///////////////////////
// TECHNIQUES //
///////////////////////
technique PostProcess
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess();
PixelShader = compile ps_3_0 PS_ProcessGaussianH();
DitherEnable=FALSE;
ZEnable=FALSE;
CullMode=NONE;
ALPHATESTENABLE=FALSE;
SEPARATEALPHABLENDENABLE=FALSE;
AlphaBlendEnable=FALSE;
StencilEnable=FALSE;
FogEnable=FALSE;
SRGBWRITEENABLE=FALSE;
}
}
technique PostProcess2
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess();
PixelShader = compile ps_3_0 PS_ProcessGaussianV();
DitherEnable=FALSE;
ZEnable=FALSE;
CullMode=NONE;
ALPHATESTENABLE=FALSE;
SEPARATEALPHABLENDENABLE=FALSE;
AlphaBlendEnable=FALSE;
StencilEnable=FALSE;
FogEnable=FALSE;
SRGBWRITEENABLE=FALSE;
}
}
technique PostProcess3
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess();
PixelShader = compile ps_3_0 PS_ProcessSoftLight();
DitherEnable=FALSE;
ZEnable=FALSE;
CullMode=NONE;
ALPHATESTENABLE=FALSE;
SEPARATEALPHABLENDENABLE=FALSE;
AlphaBlendEnable=FALSE;
StencilEnable=FALSE;
FogEnable=FALSE;
SRGBWRITEENABLE=FALSE;
}
}
technique PostProcess4
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess();
PixelShader = compile ps_3_0 PS_ProcessGaussianH();
DitherEnable=FALSE;
ZEnable=FALSE;
CullMode=NONE;
ALPHATESTENABLE=FALSE;
SEPARATEALPHABLENDENABLE=FALSE;
AlphaBlendEnable=FALSE;
StencilEnable=FALSE;
FogEnable=FALSE;
SRGBWRITEENABLE=FALSE;
}
}
technique PostProcess5
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess();
PixelShader = compile ps_3_0 PS_ProcessGaussianV();
DitherEnable=FALSE;
ZEnable=FALSE;
CullMode=NONE;
ALPHATESTENABLE=FALSE;
SEPARATEALPHABLENDENABLE=FALSE;
AlphaBlendEnable=FALSE;
StencilEnable=FALSE;
FogEnable=FALSE;
SRGBWRITEENABLE=FALSE;
}
}
technique PostProcess6
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess();
PixelShader = compile ps_3_0 PS_ProcessGaussBloom();
DitherEnable=FALSE;
ZEnable=FALSE;
CullMode=NONE;
ALPHATESTENABLE=FALSE;
SEPARATEALPHABLENDENABLE=FALSE;
AlphaBlendEnable=FALSE;
StencilEnable=FALSE;
FogEnable=FALSE;
SRGBWRITEENABLE=FALSE;
}
}
#ifdef SharpMethod
technique PostProcess7
{
pass P0
{
VertexShader = compile vs_3_0 VS_PostProcess();
PixelShader = compile ps_3_0 PS_ProcessLumaSharpen();
DitherEnable=FALSE;
ZEnable=FALSE;
CullMode=NONE;
ALPHATESTENABLE=FALSE;
SEPARATEALPHABLENDENABLE=FALSE;
AlphaBlendEnable=FALSE;
StencilEnable=FALSE;
FogEnable=FALSE;
SRGBWRITEENABLE=FALSE;
}
}
#endif