3098 lines
92 KiB
HLSL
3098 lines
92 KiB
HLSL
#ifndef AUTODANCE__FX
|
|
#define AUTODANCE__FX
|
|
|
|
#define CB_AUTODANCE
|
|
|
|
#ifdef ITF_X360
|
|
#define ALT_TOONSHADER
|
|
#endif
|
|
|
|
#if defined DX11_SHADERS || defined DX12_SHADERS
|
|
#define ALT_TOONSHADER
|
|
#endif
|
|
|
|
#include "PlatformAdapter.fxh"
|
|
#include "ShaderParameters.fxh"
|
|
|
|
REGISTER_SAMPLER(samp, 0);
|
|
REGISTER_SAMPLER(samp, 1);
|
|
REGISTER_SAMPLER(samp, 2);
|
|
REGISTER_SAMPLER(samp, 3);
|
|
|
|
#define PI 3.14159265359f
|
|
#define EPSILON 0.0001f
|
|
|
|
#define DEFINE_CONSTANTS \
|
|
const float3 rgb_to_y = float3( 0.212671f, 0.715160f, 0.072169f ); \
|
|
const float2 vec2_zero = float2(0.0f,0.0f); \
|
|
const float2 vec2_one = float2(1.0f,1.0f); \
|
|
const float3 vec3_zero = float3(0.0f,0.0f,0.0f); \
|
|
const float3 vec3_one = float3(1.0f,1.0f,1.0f); \
|
|
const float4 vec4_zero = float4(0.0f,0.0f,0.0f,0.0f); \
|
|
const float4 vec4_one = float4(1.0f,1.0f,1.0f,1.0f);
|
|
|
|
struct VS_IN
|
|
{
|
|
float4 Position : POSITION;
|
|
float2 uv0 : TEXCOORD0;
|
|
};
|
|
|
|
struct VS_OUT
|
|
{
|
|
float4 Position : VS_OUT_POS;
|
|
float2 uv0 : TEXCOORD0;
|
|
};
|
|
|
|
struct VS_OUT_T2
|
|
{
|
|
float4 Position : VS_OUT_POS;
|
|
float4 uv0 : TEXCOORD0;
|
|
};
|
|
|
|
struct VS_PLANE_OUT
|
|
{
|
|
float4 Position : VS_OUT_POS;
|
|
float2 uv0 : TEXCOORD0;
|
|
float4 pospostvs : TEXCOORD1;
|
|
|
|
};
|
|
|
|
struct PS_OUT
|
|
{
|
|
float4 clr : PS_OUT_COLOR;
|
|
};
|
|
|
|
/////////////////////////////
|
|
// Perspective correction
|
|
/////////////////////////////
|
|
|
|
struct VS_PC_IN
|
|
{
|
|
float4 Position : POSITION;
|
|
float4 col : COLOR0;
|
|
float2 uv0 : TEXCOORD0;
|
|
float4 uv1 : TEXCOORD1;
|
|
float4 uv2 : TEXCOORD2;
|
|
float2 uv3 : TEXCOORD3;
|
|
};
|
|
|
|
struct VS_PC_OUT
|
|
{
|
|
float4 Position : VS_OUT_POS;
|
|
float3 uv : TEXCOORD0;
|
|
float4 uv2 : TEXCOORD1;
|
|
};
|
|
|
|
|
|
struct VS_Particle_OUT
|
|
{
|
|
float4 Position : VS_OUT_POS;
|
|
float4 uv : TEXCOORD0;
|
|
float4 uv2 : TEXCOORD1;
|
|
};
|
|
|
|
float3 XYZ2RGB(float3 input)
|
|
{
|
|
const float3 rFactors = float3(3.2404542f, -1.5371385f, -0.4985314f);
|
|
const float3 gFactors = float3(-0.9692660f, 1.8760108f, 0.0415560f);
|
|
const float3 bFactors = float3(0.0556434f, -0.2040259f, 1.0572252f);
|
|
|
|
float r = dot(input,rFactors);
|
|
float g = dot(input,gFactors);
|
|
float b = dot(input,bFactors);
|
|
|
|
return float3(r,g,b);
|
|
}
|
|
|
|
float3 XYY2XYZ(float3 input)
|
|
{
|
|
float x = 0.0f;
|
|
float y = 0.0f;
|
|
float z = 0.0f;
|
|
|
|
if (input.y > 0.001f)
|
|
{
|
|
x = (input.x * input.z) / input.y;
|
|
y = input.z;
|
|
z = ((1.0f - input.x - input.y) * input.z) / input.y;
|
|
}
|
|
|
|
return float3(x,y,z);
|
|
}
|
|
|
|
float3 RGB2XYZ(float3 input)
|
|
{
|
|
const float3 xFactors = float3(0.4124f, 0.3576f, 0.1805f);
|
|
const float3 yFactors = float3(0.2126f, 0.7152f, 0.0722f);
|
|
const float3 zFactors = float3(0.0193f, 0.1192f, 0.9505f);
|
|
|
|
float x = dot(input,xFactors);
|
|
float y = dot(input,yFactors);
|
|
float z = dot(input,zFactors);
|
|
|
|
return float3(x,y,z);
|
|
}
|
|
|
|
float3 XYZ2XYY(float3 input)
|
|
{
|
|
float sum = max(1e-6f, input.x + input.y + input.z);
|
|
|
|
float rx = input.x / sum;
|
|
float ry = input.y / sum;
|
|
float rY = input.y;
|
|
|
|
return float3(rx,ry,rY);
|
|
}
|
|
|
|
float3 XYY2RGB(float3 input)
|
|
{
|
|
float3 valXYZ = XYY2XYZ(input);
|
|
return saturate(XYZ2RGB(valXYZ));
|
|
}
|
|
|
|
float3 RGB2XYY(float3 input)
|
|
{
|
|
float3 valXYZ = RGB2XYZ(input);
|
|
return XYZ2XYY(valXYZ);
|
|
}
|
|
|
|
#ifdef VERTEX_PROFILE
|
|
|
|
VS_OUT vs_copy_as_is( VS_IN input )
|
|
{
|
|
VS_OUT output;
|
|
output.Position = input.Position;
|
|
output.uv0 = input.uv0;
|
|
return output;
|
|
}
|
|
|
|
VS_OUT_T2 vs_copy_as_is_embedded( VS_IN input )
|
|
{
|
|
VS_OUT_T2 output;
|
|
output.Position = input.Position;
|
|
output.uv0.zw = frac(input.uv0);
|
|
output.uv0.xy = (input.uv0 - output.uv0.zw) / 256.0f;
|
|
return output;
|
|
}
|
|
|
|
VS_PLANE_OUT vs_worldviewproj(VS_IN input)
|
|
{
|
|
VS_PLANE_OUT output;
|
|
output.Position = mul(input.Position, vs_mWorldViewProjection);
|
|
output.Position.z = clamp(output.Position.z, 0.0f, output.Position.w);
|
|
output.uv0 = input.uv0;
|
|
output.pospostvs = output.Position;
|
|
|
|
return output;
|
|
}
|
|
|
|
// Perspective correction
|
|
VS_PC_OUT vs_copy_as_is_PC( VS_PC_IN input )
|
|
{
|
|
VS_PC_OUT output;
|
|
output.Position = input.Position;
|
|
output.uv = input.uv1.xyz;
|
|
output.uv2 = input.uv2;
|
|
return output;
|
|
}
|
|
#if defined( _CAFE_ ) || defined ( _NX_ )
|
|
VS_Particle_OUT vs_particles( VS_PC_IN input )
|
|
{
|
|
VS_Particle_OUT output;
|
|
output.Position = input.Position;
|
|
output.uv = float4(input.uv1.xyz,1);
|
|
output.uv2 = input.uv2;
|
|
return output;
|
|
}
|
|
#else
|
|
|
|
// particles stuff
|
|
VS_Particle_OUT vs_particles( VS_PC_IN input )
|
|
{
|
|
VS_Particle_OUT output;
|
|
|
|
const float startRadius = vs_reg0.x;
|
|
const float endRadius = vs_reg0.y;
|
|
const float minSpin = vs_reg0.z;
|
|
const float maxSpin = vs_reg0.w;
|
|
|
|
const float minWanderAmp = vs_reg1.x * 0.01f;
|
|
const float maxWanderAmp = vs_reg1.y * 0.01f;
|
|
const float radiusVar = vs_reg1.z;
|
|
const float time = vs_reg1.w;
|
|
|
|
const float minSpeed = vs_reg2.x;
|
|
const float maxSpeed = vs_reg2.y;
|
|
const float dirX = vs_reg2.z;
|
|
const float dirY = vs_reg2.w;
|
|
|
|
const float minWanderRate = vs_reg3.x;
|
|
const float maxWanderRate = vs_reg3.y;
|
|
const float radiusNoiseAmp = vs_reg3.z;
|
|
const float radiusNoiseRate = vs_reg3.w;
|
|
|
|
const float3 stColxyY = vs_reg4.xyz;
|
|
const float stAlpha = vs_reg4.w;
|
|
const float3 edColxyY = vs_reg5.xyz;
|
|
const float edAlpha = vs_reg5.w;
|
|
|
|
const float imageU = vs_reg6.x;
|
|
const float motionPower = vs_reg6.y;
|
|
const float aspect = vs_reg6.z;
|
|
|
|
const float4 randVals = input.uv1;
|
|
const float4 sinRateCoeffs = float4(1.0f,2.0f,4.0f,8.0f) * radiusNoiseRate;
|
|
const float4 sinAmpCoeffs = float4(0.53333f,0.26667f,0.13333f,0.06667f);
|
|
|
|
float2 currPos = input.Position.xy;
|
|
float2 cornerOffset = (input.uv0 * 2.0f) - float2(1.0f,1.0f);
|
|
float2 dirVector = vs_reg2.zw;
|
|
float2 edgeVector = float2(-dirVector.y,dirVector.x);
|
|
|
|
float posdot = dot(currPos,dirVector);
|
|
float edgedot = dot(currPos,edgeVector);
|
|
float currAngle = time * lerp(minSpin,maxSpin,randVals.w);
|
|
currAngle += atan2(dirVector.y,dirVector.x) - (1.57f);
|
|
|
|
float sinAng = sin(currAngle);
|
|
float cosAng = cos(currAngle);
|
|
|
|
float2 cornerPos = float2((cornerOffset.x * cosAng) + (cornerOffset.y * -sinAng),(cornerOffset.x * sinAng) + (cornerOffset.y * cosAng));
|
|
|
|
float lifeRatio = frac((time * lerp(minSpeed,maxSpeed,randVals.x)) + posdot);
|
|
lifeRatio = pow(lifeRatio,motionPower);
|
|
float linePos = ((lifeRatio * 2.0f) - 1.0f) * 1.414f;
|
|
|
|
float4 radNoiseLoops = sin((lifeRatio.xxxx + randVals) * sinRateCoeffs) * radiusNoiseAmp;
|
|
float radiusNoise = dot(radNoiseLoops,sinAmpCoeffs);
|
|
|
|
float radius = (1.0f / 40.0f) * max(0.0f,lerp(startRadius,endRadius,lifeRatio) * (1.0f + radiusNoise + (radiusVar * ((randVals.y * 2.0f) - 1.0f))));
|
|
float lineWander = sin(time * lerp(minWanderRate,maxWanderRate,randVals.z)) * lerp(minWanderAmp,maxWanderAmp,randVals.x);
|
|
|
|
float3 colRGB = XYY2RGB(lerp(stColxyY,edColxyY,lifeRatio * (0.5f + (randVals.x * 1.0f))));
|
|
float colAlpha = lerp(stAlpha,edAlpha,lifeRatio);
|
|
|
|
edgedot += lineWander;
|
|
|
|
currPos = (dirVector * linePos) + (edgeVector * edgedot);
|
|
cornerPos *= radius;
|
|
cornerPos.x *= 1.0f / aspect;
|
|
|
|
float2 finalPos = currPos + cornerPos;
|
|
|
|
output.Position = float4(finalPos,0,input.Position.w);
|
|
output.uv.xy = input.uv0;
|
|
output.uv.x *= (1.0f / 12.0f);
|
|
output.uv.x += imageU;
|
|
output.uv.z = 0.0f;
|
|
output.uv.w = 0.0f;
|
|
output.uv2 = float4(colRGB.xyz,colAlpha);
|
|
return output;
|
|
}
|
|
#endif // not _CAFE_ and not _NX_
|
|
#endif // VERTEX_PROFILE
|
|
|
|
#ifdef PIXEL_PROFILE
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Utility functions
|
|
|
|
inline float linStep( float xmin, float xmax, float x )
|
|
{
|
|
float a = 1.0/( xmax - xmin );
|
|
float b = -a * xmin;
|
|
return saturate( ( a*x )+b );
|
|
}
|
|
|
|
inline float rectFunc( float xmin, float xmax, float x )
|
|
{
|
|
return step(xmin, x) * ( 1.0f - step(xmax, x) );
|
|
}
|
|
|
|
inline float2 rectFunc( float xmin, float xmax, float2 x )
|
|
{
|
|
return step(xmin, x) * ( 1.0f - step(xmax, x) );
|
|
}
|
|
|
|
inline float3 rectFunc( float xmin, float xmax, float3 x )
|
|
{
|
|
return step(xmin, x) * ( 1.0f - step(xmax, x) );
|
|
}
|
|
|
|
inline float4 rectFunc( float4 xmin, float4 xmax, float4 x )
|
|
{
|
|
return step(xmin, x) * ( 1.0f - step(xmax, x) );
|
|
}
|
|
|
|
inline float colorDistance_max( float3 a, float3 b )
|
|
{
|
|
return max
|
|
(
|
|
max
|
|
(
|
|
abs( a.x-b.x ), abs( a.y-b.y )
|
|
),
|
|
abs( a.z-b.z )
|
|
);
|
|
}
|
|
|
|
inline float colorDistance_avg( float3 a, float3 b )
|
|
{
|
|
float3 dist = abs( a - b );
|
|
return ( dist.x + dist.y + dist.z ) / 3.0f;
|
|
}
|
|
|
|
inline float colorDistance_euclidean( float3 a, float3 b )
|
|
{
|
|
const float sqrt3 = 1.7321f;
|
|
float3 dist = abs( a - b );
|
|
return (float) length( dist ) / sqrt3;
|
|
}
|
|
|
|
inline float Max( float f1, float4 v )
|
|
{
|
|
float2 v1 = float2( v.x, v.y );
|
|
float2 v2 = float2( v.z, v.w );
|
|
v1 = max( v1, v2 );
|
|
v1 = max( v1.x, v1.y );
|
|
return max( f1, v1.x );
|
|
}
|
|
|
|
inline float Max( float4 v )
|
|
{
|
|
float2 v1 = float2( v.x, v.y );
|
|
float2 v2 = float2( v.z, v.w );
|
|
v1 = max( v1, v2 );
|
|
return max( v1.x, v1.y );
|
|
}
|
|
|
|
inline float Min( float f1, float4 v )
|
|
{
|
|
float2 v1 = float2( v.x, v.y );
|
|
float2 v2 = float2( v.z, v.w );
|
|
v1 = min( v1, v2 );
|
|
v1 = min( v1.x, v1.y );
|
|
return min( f1, v1.x );
|
|
}
|
|
|
|
inline float Min( float4 v )
|
|
{
|
|
float2 v1 = float2( v.x, v.y );
|
|
float2 v2 = float2( v.z, v.w );
|
|
v1 = min( v1, v2 );
|
|
return min( v1.x, v1.y );
|
|
}
|
|
|
|
inline float Sum( float4 v )
|
|
{
|
|
const float4 vec4_one = float4(1.0f,1.0f,1.0f,1.0f);
|
|
return dot( v, vec4_one );
|
|
}
|
|
|
|
float4 tex2D_blurFast( float2 uv, float2 texelOffset )
|
|
{
|
|
float2 off = texelOffset;
|
|
float2 off_h = off * 0.5;
|
|
|
|
float4 tCenter = TEXTURE_READ_2D( samp, 0, uv );
|
|
float4 t0 = TEXTURE_READ_2D( samp, 0, uv + float2( -off_h.x, off.y ) );
|
|
float4 t1 = TEXTURE_READ_2D( samp, 0, uv + float2( off.x, off_h.y ) );
|
|
float4 t2 = TEXTURE_READ_2D( samp, 0, uv + float2( off_h.x, -off.y ) );
|
|
float4 t3 = TEXTURE_READ_2D( samp, 0, uv + float2( -off.x, -off_h.y ) );
|
|
|
|
return( ( t0+t1+t2+t3 )*0.25*0.4 ) +( tCenter*0.6 );
|
|
}
|
|
|
|
float4 tex2D_blurG3( float2 uv, float2 texelOffset )
|
|
{
|
|
float2 off = texelOffset;
|
|
|
|
float4 res = TEXTURE_READ_2D( samp, 0, uv + float2( -1*off.x, -1*off.y ) ) *0.07511;
|
|
res += TEXTURE_READ_2D( samp, 0, uv + float2( 0*off.x, -1*off.y ) ) *0.12384;
|
|
res += TEXTURE_READ_2D( samp, 0, uv + float2( 1*off.x, -1*off.y ) ) *0.07511;
|
|
|
|
res += TEXTURE_READ_2D( samp, 0, uv + float2( -1*off.x, 0*off.y ) ) *0.12384;
|
|
res += TEXTURE_READ_2D( samp, 0, uv + float2( 0*off.x, 0*off.y ) ) *0.20418;
|
|
res += TEXTURE_READ_2D( samp, 0, uv + float2( 1*off.x, 0*off.y ) ) *0.12384;
|
|
|
|
res += TEXTURE_READ_2D( samp, 0, uv + float2( -1*off.x, 1*off.y ) ) *0.07511;
|
|
res += TEXTURE_READ_2D( samp, 0, uv + float2( 0*off.x, 1*off.y ) ) *0.12384;
|
|
res += TEXTURE_READ_2D( samp, 0, uv + float2( 1*off.x, 1*off.y ) ) *0.07511;
|
|
|
|
return res;
|
|
}
|
|
|
|
float4 tex2D_blurH( float2 uv, float2 texelOffset )
|
|
{
|
|
float2 off = texelOffset;
|
|
|
|
float4 res = TEXTURE_READ_2D( samp, 0, float2(uv.x - 4.0*off.x, uv.y)) * 0.05;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x - 3.0*off.x, uv.y)) * 0.09;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x - 2.0*off.x, uv.y)) * 0.12;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x - off.x, uv.y)) * 0.15;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x, uv.y)) * 0.16;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x + off.x, uv.y)) * 0.15;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x + 2.0*off.x, uv.y)) * 0.12;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x + 3.0*off.x, uv.y)) * 0.09;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x + 4.0*off.x, uv.y)) * 0.05;
|
|
|
|
return res;
|
|
}
|
|
|
|
float4 tex2D_blurV( float2 uv, float2 texelOffset )
|
|
{
|
|
float2 off = texelOffset;
|
|
|
|
float4 res = TEXTURE_READ_2D( samp, 0, float2(uv.x, uv.y - 4.0*off.y )) * 0.05;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x, uv.y - 3.0*off.y )) * 0.09;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x, uv.y - 2.0*off.y )) * 0.12;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x, uv.y - off.y )) * 0.15;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x, uv.y )) * 0.16;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x, uv.y + off.y )) * 0.15;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x, uv.y + 2.0*off.y )) * 0.12;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x, uv.y + 3.0*off.y )) * 0.09;
|
|
res += TEXTURE_READ_2D( samp, 0, float2(uv.x, uv.y + 4.0*off.y )) * 0.05;
|
|
|
|
return res;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Pixel Shaders( filters )
|
|
|
|
PS_OUT ps_add_color_then_blend( VS_OUT input )
|
|
{
|
|
float4 oldImage = TEXTURE_READ_2D( samp, 0, input.uv0 ) + ps_reg0;
|
|
|
|
float4 newImage = TEXTURE_READ_2D( samp, 1, input.uv0 );
|
|
|
|
float finalAlpha = newImage.w +( oldImage.w*( 1.0-newImage.w ) );
|
|
float3 finalClr =( newImage.xyz * newImage.w ) +( oldImage.xyz*oldImage.w*( 1.0-newImage.w ) );
|
|
finalClr /= finalAlpha + 0.001f;
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( finalClr, finalAlpha );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_alpha_blend( VS_OUT input )
|
|
{
|
|
float4 oldImage = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float4 newImage = TEXTURE_READ_2D( samp, 1, input.uv0 );
|
|
|
|
float finalAlpha = newImage.w +( oldImage.w*( 1.0-newImage.w ) );
|
|
float3 finalClr =( newImage.xyz * newImage.w ) +( oldImage.xyz*oldImage.w*( 1.0-newImage.w ) );
|
|
finalClr /= finalAlpha + 0.001f;
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( finalClr, finalAlpha );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_blur_g3( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
output.clr = tex2D_blurG3( input.uv0, ps_samp0Size.zw ).xyzw;
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_blur_h( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
output.clr = tex2D_blurH( input.uv0, ps_samp0Size.zw ).xyzw;
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_blur_v( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
output.clr = tex2D_blurV( input.uv0, ps_samp0Size.zw ).xyzw;
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_color_grading( VS_OUT input )
|
|
{
|
|
float3 img_c = TEXTURE_READ_2D( samp, 0, input.uv0 ).xyz;
|
|
|
|
float3 recolored;
|
|
float recoloredOpacity;
|
|
{
|
|
float3 clr3 = img_c * 0.333333;
|
|
float clr = clr3.x + clr3.y + clr3.z;
|
|
|
|
float lowToMid = ps_reg3.x;
|
|
float lowToMidWidth = ps_reg3.y;
|
|
float midToHigh = ps_reg3.z;
|
|
float midToHighWidth = ps_reg3.w;
|
|
|
|
float d0 = linStep( lowToMid+( 0.5*lowToMidWidth ), lowToMid-( 0.5*lowToMidWidth ), clr );
|
|
float d2 = linStep( midToHigh-( 0.5*midToHighWidth ), midToHigh+( 0.5*midToHighWidth ), clr );
|
|
float d1 = 1.0-( d0+d2 );
|
|
|
|
recoloredOpacity =
|
|
( d0 * ps_reg0.w )
|
|
+( d1 * ps_reg1.w )
|
|
+( d2 * ps_reg2.w );
|
|
|
|
recolored = ( ps_reg0.xyz * d0 * clr/lowToMid )
|
|
+( ps_reg1.xyz * d1 )
|
|
+( ps_reg2.xyz * d2 *( clr/( 1.0-midToHigh )+midToHigh ) );
|
|
}
|
|
|
|
#if defined DX11_SHADERS || defined DX12_SHADERS
|
|
if( ps_alphaTest.x )
|
|
{
|
|
clip( recoloredOpacity - ps_alphaTest.y );
|
|
}
|
|
#endif
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( recolored, recoloredOpacity );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_copy_as_is( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
output.clr = TEXTURE_READ_2D( samp, 0, input.uv0 ).xyzw;
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_copy_fix_edge( VS_OUT input )
|
|
{
|
|
#if 1
|
|
PS_OUT output;
|
|
output.clr = TEXTURE_READ_2D( samp, 0, input.uv0 ).xyzw;
|
|
return output;
|
|
#else
|
|
|
|
PS_OUT output;
|
|
const float2 pixelOffset = ps_samp0Size.zw * 2.0f;
|
|
|
|
const float2 UV0c = input.uv0 + float2(-pixelOffset.x,0);
|
|
const float2 UV1c = input.uv0 + float2(pixelOffset.x,0);
|
|
const float2 UVcc = input.uv0;
|
|
const float2 UVc0 = input.uv0 + float2(0,-pixelOffset.y);
|
|
const float2 UVc1 = input.uv0 + float2(0,pixelOffset.y);
|
|
|
|
float4 col = TEXTURE_READ_2D( samp, 0, UVcc);
|
|
float col0c = TEXTURE_READ_2D( samp, 0, UV0c).r;
|
|
float col1c = TEXTURE_READ_2D( samp, 0, UV1c).r;
|
|
float colcc = col.r;
|
|
float colc0 = TEXTURE_READ_2D( samp, 0, UVc0).r;
|
|
float colc1 = TEXTURE_READ_2D( samp, 0, UVc1).r;
|
|
|
|
float xdist = col1c - col0c;
|
|
float ydist = colc1 - colc0;
|
|
|
|
float dist = sqrt((xdist * xdist) + (ydist * ydist));
|
|
float scale = saturate(colcc * dist);
|
|
|
|
output.clr = scale * col;
|
|
output.clr = float4(dist.xxx,1.0f);
|
|
|
|
return output;
|
|
#endif
|
|
}
|
|
|
|
PS_OUT ps_copy_as_is_alpha_test(VS_OUT input)
|
|
{
|
|
float4 color = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
|
|
#if defined DX11_SHADERS || defined DX12_SHADERS
|
|
if( ps_alphaTest.x )
|
|
{
|
|
clip( color.a - ps_alphaTest.y );
|
|
}
|
|
#endif
|
|
|
|
PS_OUT output;
|
|
output.clr = color;
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_blend_with_mask( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
float4 clr0 = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float4 clr1 = TEXTURE_READ_2D( samp, 1, input.uv0 );
|
|
float mask = TEXTURE_READ_2D( samp, 2, input.uv0 ).r;
|
|
|
|
float4 clr = lerp( clr0, clr1, mask );
|
|
|
|
float alpha = lerp( saturate(clr0.a * ps_reg0.x + clr1.a * ps_reg0.y),
|
|
clr.a,
|
|
ps_reg0.x * ps_reg0.y );
|
|
|
|
output.clr = float4( clr.rgb, alpha );
|
|
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_blend_with_mask_color( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
float4 clr0 = ps_reg1;
|
|
float4 clr1 = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float mask = TEXTURE_READ_2D( samp, 1, input.uv0 ).r;
|
|
|
|
float4 clr = lerp( clr0, clr1, mask );
|
|
|
|
float alpha = lerp( saturate(clr0.a * ps_reg0.x + clr1.a * ps_reg0.y),
|
|
clr.a,
|
|
ps_reg0.x * ps_reg0.y );
|
|
|
|
output.clr = float4( clr.rgb, alpha );
|
|
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_blend_premul( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
float4 clr0 = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float4 clr1 = TEXTURE_READ_2D( samp, 1, input.uv0 );
|
|
|
|
clr1 *= (1.0f - clr0.a);
|
|
|
|
output.clr = float4(clr1.rgb + clr0.rgb,1.0f);
|
|
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_smoothstepped_img( VS_OUT input )
|
|
{
|
|
float playerMask = TEXTURE_READ_2D( samp, 1, input.uv0 /*- float2( ps_samp1Size.z*2, -ps_samp1Size.w*2 )*/ ).x;
|
|
playerMask = linStep( ps_reg2.x, ps_reg2.y, playerMask );
|
|
float4 color = float4( TEXTURE_READ_2D( samp, 0, input.uv0 ).xyz, playerMask );
|
|
|
|
PS_OUT output;
|
|
output.clr = color;
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_spike_clr( VS_OUT input )
|
|
{
|
|
float tinput = TEXTURE_READ_2D( samp, 1, input.uv0 - float2( ps_samp1Size.z*2, -ps_samp1Size.w*2 ) ).x;
|
|
|
|
float middle = ps_reg2.x;
|
|
float thickness = ps_reg2.y;
|
|
float smoothFactor = ps_reg2.z;
|
|
|
|
float lowStart = middle -( thickness*0.5 ) - smoothFactor;
|
|
float lowEnd = middle -( thickness*0.5 );
|
|
float highStart = middle +( thickness*0.5 ) + smoothFactor;
|
|
float highEnd = middle +( thickness*0.5 );
|
|
|
|
float contourMask = min(
|
|
smoothstep( lowStart, lowEnd, tinput ),
|
|
smoothstep( highStart, highEnd, tinput ) );
|
|
|
|
#if defined DX11_SHADERS || defined DX12_SHADERS
|
|
if( ps_alphaTest.x )
|
|
{
|
|
clip( (ps_reg3.w*contourMask) - ps_alphaTest.y );
|
|
}
|
|
#endif
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( ps_reg3.xyz, ps_reg3.w*contourMask );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mul_color( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
|
|
output.clr = TEXTURE_READ_2D( samp, 0, input.uv0 ).xyzw;
|
|
output.clr *= ps_reg0;
|
|
return output;
|
|
}
|
|
|
|
#if defined DX11_SHADERS || defined DX12_SHADERS
|
|
float GetIRBulbCorrection(float2 screenUV)
|
|
{
|
|
float2 posVal,posExp;
|
|
|
|
float val = 0.0f;
|
|
float2 pos = screenUV;
|
|
pos *= 2.0f;
|
|
pos -= 1.0f;
|
|
pos.y *= -1.0f;
|
|
|
|
pos = (pos * float2(2.307619f,1.216094f)) + float2(-0.430332f,-0.036529f);
|
|
pos = pos * pos;
|
|
|
|
posExp = pos * float2(-0.921264f,-0.683528f);
|
|
posVal = float2(0.474407f,0.779357f) / (1.0f - (posExp * 0.93138945f) + (posExp * posExp * 0.79807341f));
|
|
|
|
val += posVal.x * posVal.y;
|
|
pos = (pos * float2(4.335279f,2.030378f)) + float2(0.109023f,-0.406690f);
|
|
pos = pos * pos;
|
|
|
|
posExp = pos * float2(-0.004911f,-0.419739f);
|
|
posVal = float2(0.945161f,0.999998f) / (1.0f - (posExp * 0.93138945f) + (posExp * posExp * 0.79807341f));
|
|
|
|
val += posVal.x * posVal.y;
|
|
pos = (pos * float2(0.064690f,6.608789f)) + float2(0.521754f,-0.082028f);
|
|
pos = pos * pos;
|
|
|
|
posExp = pos * float2(-0.134696f,-0.393378f);
|
|
posVal = float2(0.213287f,-0.909062f) / (1.0f - (posExp * 0.93138945f) + (posExp * posExp * 0.79807341f));
|
|
|
|
val += posVal.x * posVal.y;
|
|
pos = (pos * float2(4.686698f,1.812515f)) + float2(-0.245583f,-0.135284f);
|
|
pos = pos * pos;
|
|
|
|
posExp = pos * float2(-0.422476f,-0.000599f);
|
|
posVal = float2(-0.482204f,0.487757f) / (1.0f - (posExp * 0.93138945f) + (posExp * posExp * 0.79807341f));
|
|
|
|
val += posVal.x * posVal.y;
|
|
//< subtle balance bodge to avoid any zero divides.
|
|
val = 0.01f + (val * 0.99f);
|
|
return 1.0f / saturate(val);
|
|
}
|
|
|
|
float ApplyImprovementMask( float player, VS_OUT input, float discrete )
|
|
{
|
|
//< get centre pixel values for IR, depth and player ID
|
|
const float offx = 4.0f / (512.0f * 1.99f);
|
|
const float offy = 4.0f / (424.0f * 1.99f);
|
|
const float2 uv0c = float2(-offx,0) + input.uv0;
|
|
const float2 uv1c = float2(offx,0) + input.uv0;
|
|
const float2 uvc0 = float2(0,-offy) + input.uv0;
|
|
const float2 uvc1 = float2(0,offy) + input.uv0;
|
|
|
|
float lumcc = TEXTURE_READ_2D( samp , 2, input.uv0).r;
|
|
float lumIR = TEXTURE_READ_2D( samp , 1, input.uv0).r;
|
|
|
|
float bulbCorrection = GetIRBulbCorrection(input.uv0);
|
|
lumIR = lumIR * bulbCorrection;
|
|
|
|
float originalIR = lumIR;
|
|
|
|
float IRDist = lumIR * (lumcc * lumcc);
|
|
|
|
float lum0c = TEXTURE_READ_2D( samp, 2, uv0c ).r;
|
|
float lum1c = TEXTURE_READ_2D( samp, 2, uv1c ).r;
|
|
float lumc0 = TEXTURE_READ_2D( samp, 2, uvc0 ).r;
|
|
float lumc1 = TEXTURE_READ_2D( samp, 2, uvc1 ).r;
|
|
|
|
float4 plPixels = float4(TEXTURE_READ_2D( samp, 0, uv0c ).r,TEXTURE_READ_2D( samp, 0, uv1c ).r,TEXTURE_READ_2D( samp, 0, uvc0 ).r,TEXTURE_READ_2D( samp, 0, uvc1 ).r);
|
|
|
|
float avgs = dot(plPixels,float4(0.25f,0.25f,0.25f,0.25f));//< calculate the average depth
|
|
float errx = abs(lumcc - ((lum0c + lum1c) * 0.5f)); //< estimate the error in depth across the pixel on the X axis (the general pixel error without light atenuation bais)
|
|
float erry = abs(lumcc - ((lumc0 + lumc1) * 0.5f)); //< estimate the error in depth across the pixel on the Y axis (the general pixel error without light atenuation bais)
|
|
|
|
float errScale = exp(-50.0f * (errx + erry));
|
|
|
|
float lum = saturate(errScale * (IRDist * 300000.0f));
|
|
|
|
lum *= step( 0.3f, lum );
|
|
|
|
lum = lerp( lum, ceil(lum), discrete );
|
|
|
|
return player * lum;
|
|
}
|
|
#endif
|
|
|
|
PS_OUT ps_player_ir_correction( VS_OUT input )
|
|
{
|
|
float player = TEXTURE_READ_2D( samp, 0, input.uv0 ).x;
|
|
|
|
#if defined DX11_SHADERS || defined DX12_SHADERS
|
|
player = ApplyImprovementMask( player, input, ps_reg0.x );
|
|
#endif
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( player, player, player, player );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_player_to_rgba( VS_OUT input )
|
|
{
|
|
float player = saturate( TEXTURE_READ_2D( samp, 0, input.uv0 ).x * 255.0 );
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( player, player, player, player );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_player_to_rgba_extract( VS_OUT input )
|
|
{
|
|
float playerVal = TEXTURE_READ_2D( samp, 0, input.uv0 ).x;
|
|
float player = rectFunc( ps_reg0.x, ps_reg0.y, playerVal );
|
|
player = saturate( player * 255.0 );
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( player, player, player, player );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_rgba_to_yuv( VS_OUT input )
|
|
{
|
|
float3 rgb = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z*0.25, 0.0 ) );
|
|
float3 rgbRight = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z*1.25, 0.0 ) ).xyz;
|
|
|
|
PS_OUT output;
|
|
|
|
output.clr.a = -0.148*rgb.r - 0.291*rgb.g + 0.439*rgb.b + (128.0/255.0); // U
|
|
output.clr.b = 0.257*rgb.r + 0.504*rgb.g + 0.098*rgb.b + ( 16.0/255.0); // Y
|
|
output.clr.g = 0.439*rgbRight.r - 0.368*rgbRight.g - 0.071*rgbRight.b + (128.0/255.0); // V
|
|
output.clr.r = 0.257*rgbRight.r + 0.504*rgbRight.g + 0.098*rgbRight.b + ( 16.0/255.0); // Y
|
|
|
|
#if defined(ITF_WIN32)
|
|
// Windows DX9 & DX11
|
|
output.clr.rgba = output.clr.gbar;
|
|
#elif defined(DX11_SHADERS) || defined(DX12_SHADERS)
|
|
// Durango & Orbis
|
|
output.clr.rgba = output.clr.gbar;
|
|
#elif defined(_CAFE_) || defined(_NX_)
|
|
// Cafe
|
|
output.clr.rgba = output.clr.abgr; // Output actual UYVY
|
|
#endif
|
|
|
|
return output;
|
|
}
|
|
|
|
float4 calcSobel_samp0(VS_OUT In,float edgeWidth,float colScale)
|
|
{
|
|
float2 offset = ps_samp0Size.zw*edgeWidth;
|
|
float OffsetX = offset.x;
|
|
float OffsetY = offset.y;
|
|
|
|
float4 s00 = TEXTURE_READ_2D( samp, 0, In.uv0 + ( float2( -OffsetX, -OffsetY ) ) );
|
|
float4 s01 = TEXTURE_READ_2D( samp, 0, In.uv0 + ( float2( 0.0, -OffsetY ) ) );
|
|
float4 s02 = TEXTURE_READ_2D( samp, 0, In.uv0 + ( float2( OffsetX, -OffsetY ) ) );
|
|
|
|
float4 s10 = TEXTURE_READ_2D( samp, 0, In.uv0 + ( float2( -OffsetX, 0.0 ) ) );
|
|
float4 s12 = TEXTURE_READ_2D( samp, 0, In.uv0 + ( float2( OffsetX, 0.0 ) ) );
|
|
|
|
float4 s20 = TEXTURE_READ_2D( samp, 0, In.uv0 + ( float2( -OffsetX, OffsetY ) ) );
|
|
float4 s21 = TEXTURE_READ_2D( samp, 0, In.uv0 + ( float2( 0.0, OffsetY ) ) );
|
|
float4 s22 = TEXTURE_READ_2D( samp, 0, In.uv0 + ( float2( OffsetX, OffsetY ) ) );
|
|
|
|
// Calc X gradient
|
|
float4 GradX = s00 + 2.0*s10 + s20 - ( s02 + 2.0*s12 + s22 );
|
|
float4 GradY = s00 + 2.0*s01 + s02 - ( s20 + 2.0*s21 + s22 );
|
|
float asum = max(max(max(s00.a,s01.a),max(s02.a,s10.a)),max(max(s12.a,s20.a),max(s21.a,s22.a)));
|
|
|
|
#if defined DX11_SHADERS || defined DX12_SHADERS
|
|
if( ps_alphaTest.x )
|
|
{
|
|
clip( asum - ps_alphaTest.y );
|
|
}
|
|
#endif
|
|
|
|
float4 SquareGrad = GradX*GradX + GradY*GradY;
|
|
float4 final = sqrt( SquareGrad )*colScale;
|
|
final.rgb *= asum;
|
|
|
|
return final;
|
|
}
|
|
|
|
float4 calcSobel_samp1(VS_OUT In,float edgeWidth,float colScale)
|
|
{
|
|
float2 offset = ps_samp0Size.zw*edgeWidth;
|
|
float OffsetX = offset.x;
|
|
float OffsetY = offset.y;
|
|
|
|
float4 s00 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( -OffsetX, -OffsetY ) ) );
|
|
float4 s01 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( 0.0, -OffsetY ) ) );
|
|
float4 s02 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( OffsetX, -OffsetY ) ) );
|
|
|
|
float4 s10 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( -OffsetX, 0.0 ) ) );
|
|
float4 s12 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( OffsetX, 0.0 ) ) );
|
|
|
|
float4 s20 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( -OffsetX, OffsetY ) ) );
|
|
float4 s21 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( 0.0, OffsetY ) ) );
|
|
float4 s22 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( OffsetX, OffsetY ) ) );
|
|
|
|
// Calc X gradient
|
|
float4 GradX = s00 + 2.0*s10 + s20 - ( s02 + 2.0*s12 + s22 );
|
|
float4 GradY = s00 + 2.0*s01 + s02 - ( s20 + 2.0*s21 + s22 );
|
|
float asum = max(max(max(s00.a,s01.a),max(s02.a,s10.a)),max(max(s12.a,s20.a),max(s21.a,s22.a)));
|
|
|
|
#if defined DX11_SHADERS || defined DX12_SHADERS
|
|
if( ps_alphaTest.x )
|
|
{
|
|
clip( asum - ps_alphaTest.y );
|
|
}
|
|
#endif
|
|
|
|
float4 SquareGrad = GradX*GradX + GradY*GradY;
|
|
float4 final = sqrt( SquareGrad )*colScale;
|
|
final.rgb *= asum;
|
|
|
|
return final;
|
|
}
|
|
|
|
float4 calcSobelGradiant_samp1Red(VS_OUT In,float edgeWidth,float scale)
|
|
{
|
|
float2 offset = ps_samp0Size.zw*edgeWidth;
|
|
float OffsetX = offset.x;
|
|
float OffsetY = offset.y;
|
|
|
|
float s00 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( -OffsetX, -OffsetY ) ) ).x;
|
|
float s01 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( 0.0, -OffsetY ) ) ).x;
|
|
float s02 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( OffsetX, -OffsetY ) ) ).x;
|
|
|
|
float s10 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( -OffsetX, 0.0 ) ) ).x;
|
|
float s11 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( 0.0, 0.0 ) ) ).x;
|
|
float s12 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( OffsetX, 0.0 ) ) ).x;
|
|
|
|
float s20 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( -OffsetX, OffsetY ) ) ).x;
|
|
float s21 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( 0.0, OffsetY ) ) ).x;
|
|
float s22 = TEXTURE_READ_2D( samp, 1, In.uv0 + ( float2( OffsetX, OffsetY ) ) ).x;
|
|
|
|
float2 Grad = float2(s00 + 2.0*s10 + s20 - ( s02 + 2.0*s12 + s22 ),s00 + 2.0*s01 + s02 - ( s20 + 2.0*s21 + s22 ));
|
|
|
|
float4 bright0 = float4(s00,s01,s02,s10);
|
|
float4 bright1 = float4(s12,s20,s21,s22);
|
|
|
|
//< 9-tap gaussian on red channel only
|
|
float bright0Avg = dot(bright0,float4(0.07511f,0.12384f,0.07511f,0.12384f));
|
|
float bright1Avg = dot(bright1,float4(0.12384,0.07511,0.12384f,0.07511f));
|
|
float brightAvg = bright0Avg + bright1Avg + (s11.x * 0.20418);
|
|
|
|
float sobel = sqrt(dot(Grad,Grad)) * scale;
|
|
|
|
float4 final = float4(Grad.x * scale,Grad.y * scale,brightAvg,sobel);
|
|
|
|
return final;
|
|
}
|
|
|
|
//#ifdef ALT_TOONSHADER
|
|
//PS_OUT ps_sobel_colored( VS_OUT In )
|
|
//{
|
|
// float4 FragCol = calcSobel_samp0(In,1.0f,1.0f);
|
|
//
|
|
// PS_OUT output;
|
|
// output.clr = FragCol;
|
|
// return output;
|
|
//}
|
|
//#else
|
|
PS_OUT ps_sobel_colored( VS_OUT input )
|
|
{
|
|
float3 img_c = TEXTURE_READ_2D( samp, 0, input.uv0 ).xyz;
|
|
float3 img_l = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z, 0.0 ) ).xyz;
|
|
float3 img_r = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, 0.0 ) ).xyz;
|
|
float3 img_u = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, ps_samp0Size.w ) ).xyz;
|
|
float3 img_d = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, -ps_samp0Size.w ) ).xyz;
|
|
|
|
float4 sobel;
|
|
{
|
|
float l_dot = colorDistance_euclidean( img_c, img_l );
|
|
float r_dot = colorDistance_euclidean( img_c, img_r );
|
|
float max_lr = max( l_dot, r_dot );
|
|
|
|
float u_dot = colorDistance_euclidean( img_c, img_u );
|
|
float d_dot = colorDistance_euclidean( img_c, img_d );
|
|
float max_ud = max( u_dot, d_dot );
|
|
|
|
float delta = max( max_lr, max_ud );
|
|
sobel = ps_reg2;
|
|
sobel.w *= saturate( pow( delta, ps_reg0.x ) * ps_reg0.y );
|
|
}
|
|
|
|
PS_OUT output;
|
|
output.clr = sobel;
|
|
return output;
|
|
}
|
|
//#endif
|
|
|
|
PS_OUT ps_yuv_pack_to_rgba( VS_OUT input )
|
|
{
|
|
float2 clr = TEXTURE_READ_2D( samp, 0, input.uv0 ).xy;
|
|
float2 clrRight = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, 0.0 ) ).xy;
|
|
float2 clrLeft = TEXTURE_READ_2D( samp, 0, input.uv0 - float2( ps_samp0Size.z, 0.0 ) ).xy;
|
|
|
|
float Fact = 1.164123535;
|
|
float3 Crc = float3( 1.595794678, -0.813476563, 0.0 );
|
|
float3 Crb = float3( 0.0, -0.391448975, 2.017822266 );
|
|
float3 Adj = float3( -0.87065506, 0.529705048, -1.081668854 );
|
|
float3x3 matToRgb = float3x3(
|
|
float3(Crc.x, Crc.y, Crc.z),
|
|
float3(Crb.x, Crb.y, Crb.z),
|
|
float3(Adj.x, Adj.y, Adj.z) );
|
|
|
|
float y, u, v;
|
|
|
|
int isOdd = floor( input.uv0.x * ps_samp0Size.x );
|
|
isOdd = isOdd -( ( isOdd / 2 ) * 2 );
|
|
|
|
y = clr.x;
|
|
if( isOdd )
|
|
{
|
|
u = clrLeft.y;
|
|
v = clr.y;
|
|
}
|
|
else
|
|
{
|
|
u = clr.y;
|
|
v = clrRight.y;
|
|
}
|
|
|
|
float3 res = mul( float3( v, u, 1.0 ), matToRgb );
|
|
res += float3( y, y, y ) * Fact;
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( res, 1.0 );
|
|
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_yuv_to_yuv_pack( VS_OUT input )
|
|
{
|
|
// unpack YUV :
|
|
// x <=> Y
|
|
// y <=> U
|
|
// z <=> Y
|
|
|
|
// packed YUV :
|
|
// x <=> U or V( half rez )
|
|
// y <=> Y
|
|
|
|
float3 yuv = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float3 yuv_right = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, 0.0 ) ).xyz;
|
|
float3 yuv_left = TEXTURE_READ_2D( samp, 0, input.uv0 - float2( ps_samp0Size.z, 0.0 ) ).xyz;
|
|
|
|
float3 yuv_pack;
|
|
|
|
int isOdd = floor( input.uv0.x * ps_samp0Size.x );
|
|
isOdd = isOdd -( ( isOdd / 2 ) * 2 );
|
|
if( isOdd )
|
|
{
|
|
yuv_pack.y = yuv.x; // Y
|
|
yuv_pack.x =( yuv.z + yuv_left.z ) * 0.5; //V
|
|
yuv_pack.z = 0.0;
|
|
}
|
|
else
|
|
{
|
|
yuv_pack.y = yuv.x; // Y
|
|
yuv_pack.x =( yuv.y + yuv_right.y ) * 0.5; //U
|
|
yuv_pack.z = 0.0;
|
|
}
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( yuv_pack, 1.0 );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_copy_depth( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
float depth = TEXTURE_READ_2D( samp, 0, input.uv0 ).x;
|
|
|
|
float band_size = ps_reg0.x;
|
|
float banded = fmod(depth.x, band_size);
|
|
float contour = abs((banded / (band_size / 2)) - 1);
|
|
|
|
output.clr.rgba = float4(depth.x, contour, depth.x, 1);
|
|
|
|
return output;
|
|
}
|
|
|
|
// RGB / HSL conversions
|
|
float3 rgb_to_hsl(float3 rgb)
|
|
{
|
|
float3 hsl = 0;
|
|
float2 MinMax;
|
|
float delta;
|
|
|
|
MinMax.x = min( rgb.r, min(rgb.g, rgb.b) );
|
|
MinMax.y = max( rgb.r, max(rgb.g, rgb.b) );
|
|
|
|
hsl.z = 0.5 * (MinMax.x + MinMax.y);
|
|
|
|
if (MinMax.x != MinMax.y)
|
|
{
|
|
delta = (MinMax.y - MinMax.x);
|
|
|
|
if (hsl.z > 0.5)
|
|
hsl.y = delta / (2 - MinMax.x - MinMax.y);
|
|
else
|
|
hsl.y = delta / (MinMax.x + MinMax.y);
|
|
|
|
if (rgb.r == MinMax.y)
|
|
hsl.x = ( (rgb.g - rgb.b) / delta );
|
|
else if (rgb.g == MinMax.y)
|
|
hsl.x = 2 + (rgb.b - rgb.r) / delta;
|
|
else
|
|
hsl.x = 4 + (rgb.r - rgb.g) / delta;
|
|
|
|
hsl.x /= 6.0;
|
|
|
|
if (hsl.x < 0.0)
|
|
hsl.x += 1.0;
|
|
}
|
|
|
|
return hsl;
|
|
}
|
|
|
|
float hsl_value(float n1, float n2, float hue)
|
|
{
|
|
float val;
|
|
|
|
if (hue > 6.0)
|
|
hue -= 6.0;
|
|
else if (hue < 0.0)
|
|
hue += 6.0;
|
|
|
|
if (hue < 1.0)
|
|
val = n1 + (n2 - n1) * hue;
|
|
else if (hue < 3.0)
|
|
val = n2;
|
|
else if (hue < 4.0)
|
|
val = n1 + (n2 - n1) * (4.0 - hue);
|
|
else
|
|
val = n1;
|
|
|
|
return val;
|
|
}
|
|
|
|
float3 hsl_to_rgb(float3 hsl)
|
|
{
|
|
float3 rgb = 0;
|
|
|
|
if (hsl.y == 0)
|
|
{
|
|
rgb.r = hsl.z;
|
|
rgb.g = hsl.z;
|
|
rgb.b = hsl.z;
|
|
}
|
|
else
|
|
{
|
|
float m1, m2;
|
|
|
|
if (hsl.z <= 0.5)
|
|
m2 = hsl.z * (1.0 + hsl.y);
|
|
else
|
|
m2 = hsl.z + hsl.y - hsl.z * hsl.y;
|
|
|
|
m1 = 2.0 * hsl.z - m2;
|
|
|
|
rgb.r = hsl_value (m1, m2, hsl.x * 6.0 + 2.0);
|
|
rgb.g = hsl_value (m1, m2, hsl.x * 6.0);
|
|
rgb.b = hsl_value (m1, m2, hsl.x * 6.0 - 2.0);
|
|
}
|
|
|
|
return rgb;
|
|
}
|
|
|
|
// Contrast
|
|
float EnhanceContrast(float lighting)
|
|
{
|
|
float weight = step(0.5f, lighting);
|
|
float lNew = smoothstep(0.0f, 1.0f, lighting);
|
|
lNew = lNew * 2.0f - 1.0f;
|
|
lNew = lerp( saturate(pow(lNew + 1, ps_reg0.z)), saturate(pow(1 - lNew, ps_reg0.z)), weight );
|
|
lNew = lerp( lNew - 1, 1 - lNew, weight );
|
|
lNew = lNew * 0.5f + 0.5f;
|
|
return lNew;
|
|
}
|
|
|
|
// UV Blackout
|
|
PS_OUT ps_uv_blackout( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
|
|
output.clr = TEXTURE_READ_2D( samp, 0, input.uv0 ).xyzw;
|
|
float lightness = TEXTURE_READ_2D( samp, 1, input.uv0 ).a;
|
|
|
|
// Convert to HSL
|
|
float3 hsl = rgb_to_hsl( output.clr.rgb );
|
|
|
|
// Desaturate
|
|
hsl.y *= ps_reg0.y;
|
|
|
|
// Enhance lighting contrast
|
|
hsl.z = EnhanceContrast(lightness);
|
|
|
|
// Convert to RGB
|
|
float3 clr = hsl_to_rgb( hsl );
|
|
|
|
// Negative
|
|
clr = 1 - clr;
|
|
|
|
// Tint
|
|
clr *= ps_reg1.rgb;
|
|
|
|
// Brightness
|
|
clr += ps_reg0.w;
|
|
|
|
// Factor
|
|
output.clr.rgb = lerp( output.clr.rgb, clr, ps_reg0.x );
|
|
|
|
return output;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// 3x3 Median
|
|
// Based on Morgan McGuire and Kyle Whitson implementation in Shader X6
|
|
|
|
#define s2(a, b) temp = a; a = min(a, b); b = max(temp, b);
|
|
#define mn3(a, b, c) s2(a, b); s2(a, c);
|
|
#define mx3(a, b, c) s2(b, c); s2(a, c);
|
|
|
|
#define mnmx3(a, b, c) mx3(a, b, c); s2(a, b); // 3 exchanges
|
|
#define mnmx4(a, b, c, d) s2(a, b); s2(c, d); s2(a, c); s2(b, d); // 4 exchanges
|
|
#define mnmx5(a, b, c, d, e) s2(a, b); s2(c, d); mn3(a, c, e); mx3(b, d, e); // 6 exchanges
|
|
#define mnmx6(a, b, c, d, e, f) s2(a, d); s2(b, e); s2(c, f); mn3(a, b, c); mx3(d, e, f); // 7 exchanges
|
|
|
|
float4 ps_autodance_median3x3( VS_OUT In, float4 clrCenter )
|
|
{
|
|
const float offx = 1.0f / 900.0f;
|
|
const float offy = 1.0f / 600.0f;
|
|
|
|
float4 v[9], temp;
|
|
|
|
v[0] = TEXTURE_READ_2D( samp, 0, In.uv0 + float2( -offx, -offy ) ).xyzw;
|
|
v[1] = TEXTURE_READ_2D( samp, 0, In.uv0 + float2( 0.0, -offy ) ).xyzw;
|
|
v[2] = TEXTURE_READ_2D( samp, 0, In.uv0 + float2( offx, -offy ) ).xyzw;
|
|
v[3] = TEXTURE_READ_2D( samp, 0, In.uv0 + float2( -offx, 0.0 ) ).xyzw;
|
|
v[4] = clrCenter;
|
|
v[5] = TEXTURE_READ_2D( samp, 0, In.uv0 + float2( offx, 0.0 ) ).xyzw;
|
|
v[6] = TEXTURE_READ_2D( samp, 0, In.uv0 + float2( -offx, offy ) ).xyzw;
|
|
v[7] = TEXTURE_READ_2D( samp, 0, In.uv0 + float2( 0.0, offy ) ).xyzw;
|
|
v[8] = TEXTURE_READ_2D( samp, 0, In.uv0 + float2( offx, offy ) ).xyzw;
|
|
|
|
// Starting with a subset of size 6, remove the min and max each time
|
|
mnmx6(v[0], v[1], v[2], v[3], v[4], v[5]);
|
|
mnmx5(v[1], v[2], v[3], v[4], v[6]);
|
|
mnmx4(v[2], v[3], v[4], v[7]);
|
|
mnmx3(v[3], v[4], v[8]);
|
|
|
|
return v[4];
|
|
}
|
|
#ifdef ALT_TOONSHADER
|
|
// Toon shader
|
|
PS_OUT ps_toon( VS_OUT input )
|
|
{
|
|
DEFINE_CONSTANTS;
|
|
|
|
PS_OUT output;
|
|
|
|
float4 clrCenter = TEXTURE_READ_2D( samp, 0, input.uv0 ).rgba;
|
|
|
|
float4 col = ps_autodance_median3x3(input, clrCenter);
|
|
|
|
// Convert to HSL
|
|
float3 hsl = rgb_to_hsl( col.rgb );
|
|
|
|
// apply toon banding.
|
|
hsl.z = (ceil((hsl.z * ps_reg0.y) + 0.5f) - 0.5f) / ps_reg0.y;
|
|
hsl.y = (ceil((hsl.y * ps_reg0.y) + 0.5f) - 0.5f) / ps_reg0.y;
|
|
|
|
// Convert back to RGB
|
|
float3 clr = hsl_to_rgb( hsl );
|
|
float4 refCol = float4(clr,1);
|
|
|
|
// Factor
|
|
output.clr.rgb = lerp( clrCenter.rgb, refCol.rgb, ps_reg0.x );
|
|
output.clr.a = col.a;
|
|
|
|
return output;
|
|
}
|
|
|
|
float SmoothRect(float x,float loStart,float loRange,float hiStart,float hiRange)
|
|
{
|
|
float lo = ((x - loStart) / loRange);
|
|
float hi = 1.0 - ((x - hiStart) / hiRange);
|
|
float res = min(lo,hi);
|
|
return saturate(res);
|
|
}
|
|
|
|
PS_OUT ps_toon_outline( VS_OUT input )
|
|
{
|
|
DEFINE_CONSTANTS;
|
|
|
|
PS_OUT output;
|
|
|
|
const float lowThreshold = 0.01f;
|
|
const float highThreshold = 1.0f - lowThreshold;
|
|
|
|
float4 playerMaskData = calcSobelGradiant_samp1Red(input,4.0f,0.25f);
|
|
float playerMask = max(0,playerMaskData.z - (0.5f * (saturate(((1.0f - playerMaskData.z) - 0.5f) * 2.0f) * (1.0f - playerMaskData.w))));
|
|
|
|
output.clr = TEXTURE_READ_2D( samp, 0, input.uv0 ).rgba;
|
|
|
|
float finalAlpha = SmoothRect(playerMask,0.0f,0.1f,0.6f,0.2f) * ps_reg1.x;
|
|
float colBW = (1.0f - saturate((playerMask - 0.35f) * 10.0f)) * finalAlpha;
|
|
|
|
float4 outline = float4(colBW.xxx,finalAlpha);
|
|
|
|
output.clr = (output.clr * (1.0f - outline.a)) + outline;
|
|
|
|
return output;
|
|
}
|
|
#else
|
|
// Toon shader
|
|
PS_OUT ps_toon( VS_OUT input )
|
|
{
|
|
DEFINE_CONSTANTS;
|
|
|
|
PS_OUT output;
|
|
|
|
output.clr = TEXTURE_READ_2D( samp, 0, input.uv0 ).rgba;
|
|
float sobel = TEXTURE_READ_2D( samp, 1, input.uv0 ).w;
|
|
|
|
// Convert to HSL
|
|
float3 hsl = rgb_to_hsl( output.clr );
|
|
|
|
float lightness = hsl.z;
|
|
|
|
// Cut out
|
|
float bandSize = floor( 256.0f / ps_reg0.y );
|
|
float bandIndex = 1.0f + floor(hsl.z * 255.0f / bandSize);
|
|
hsl.z = saturate( bandIndex * bandSize / 255.0f );
|
|
|
|
// Convert to RGB
|
|
float3 clr = hsl_to_rgb( hsl );
|
|
|
|
// Multiply blend mode
|
|
clr *= clr;
|
|
|
|
// Overlay blend mode
|
|
float weight = step(0.5f, lightness);
|
|
clr = lerp(
|
|
clamp( pow(clr * output.clr.rgb, ps_reg0.z), vec3_zero, output.clr.rgb ),
|
|
vec3_one - (vec3_one - clr) * (vec3_one - output.clr.rgb),
|
|
weight);
|
|
|
|
// Photocopy filter
|
|
clr *= 1.0f - sobel;
|
|
|
|
// Factor
|
|
output.clr.rgb = lerp( output.clr.rgb, clr, ps_reg0.x );
|
|
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_toon_outline( VS_OUT input )
|
|
{
|
|
DEFINE_CONSTANTS;
|
|
|
|
PS_OUT output;
|
|
|
|
const float lowThreshold = 0.01f;
|
|
const float highThreshold = 1.0f - lowThreshold;
|
|
|
|
output.clr = TEXTURE_READ_2D( samp, 0, input.uv0 ).rgba;
|
|
|
|
float playerMask = TEXTURE_READ_2D( samp, 1, input.uv0 ).x;
|
|
|
|
// Black contour
|
|
|
|
float middle = ps_reg0.x;
|
|
float thickness = ps_reg0.y;
|
|
float smoothFactor = ps_reg0.z;
|
|
|
|
float lowStart = middle -( thickness*0.5 ) - smoothFactor;
|
|
float lowEnd = middle -( thickness*0.5 );
|
|
float highStart = middle +( thickness*0.5 ) + smoothFactor;
|
|
float highEnd = middle +( thickness*0.5 );
|
|
|
|
lowStart = max(lowStart, lowThreshold);
|
|
lowEnd = max(lowEnd, lowThreshold);
|
|
highStart = min(highStart, highThreshold);
|
|
highEnd = min(highEnd, highThreshold);
|
|
|
|
float contourMaskBlack = min(
|
|
smoothstep( lowStart, lowEnd, playerMask ),
|
|
smoothstep( highStart, highEnd, playerMask ) );
|
|
|
|
// White contour
|
|
|
|
middle = middle - (0.5 * ps_reg0.w * thickness + 0.5 * thickness + smoothFactor);
|
|
thickness *= ps_reg0.w;
|
|
|
|
lowStart = middle -( thickness*0.5 ) - smoothFactor;
|
|
lowEnd = middle -( thickness*0.5 );
|
|
highStart = middle +( thickness*0.5 ) + smoothFactor;
|
|
highEnd = middle +( thickness*0.5 );
|
|
|
|
lowStart = max(lowStart, lowThreshold);
|
|
lowEnd = max(lowEnd, lowThreshold);
|
|
highStart = min(highStart, highThreshold);
|
|
highEnd = min(highEnd, highThreshold);
|
|
|
|
float contourMaskWhite = min(
|
|
smoothstep( lowStart, lowEnd, playerMask ),
|
|
smoothstep( highStart, highEnd, playerMask ) );
|
|
|
|
// Blend
|
|
|
|
float4 clr = output.clr;
|
|
clr.rgb = lerp( clr.rgb, vec3_one, contourMaskWhite );
|
|
clr.rgb = lerp( clr.rgb, vec3_zero, contourMaskBlack );
|
|
|
|
// Set Alpha at the outline
|
|
clr.a = lerp( output.clr.a, 1.0f, max( contourMaskWhite, contourMaskBlack ) );
|
|
|
|
// Factor
|
|
output.clr = lerp( output.clr, clr, ps_reg1.x );
|
|
|
|
return output;
|
|
}
|
|
#endif
|
|
|
|
// Half tone
|
|
PS_OUT ps_half_tone( VS_OUT input )
|
|
{
|
|
const float factor = 0.35f;
|
|
|
|
PS_OUT output;
|
|
|
|
output.clr = TEXTURE_READ_2D( samp, 0, input.uv0 ).xyzw;
|
|
float lightness = TEXTURE_READ_2D( samp, 2, input.uv0 ).r;
|
|
|
|
// Convert to HSL
|
|
float3 hsl = rgb_to_hsl( output.clr );
|
|
|
|
// Cut out
|
|
float bandSize = floor( 256.0f / ps_reg0.y );
|
|
float bandIndex = clamp( floor(hsl.z * 255.0f / bandSize), 1.0f, ps_reg0.y );
|
|
hsl.z = bandIndex * bandSize / 255.0f;
|
|
|
|
// Convert to RGB
|
|
float3 clr = hsl_to_rgb( hsl );
|
|
|
|
// Apply halftone pattern
|
|
const float4 xmin = float4(0.0f, 0.15f, 0.3f, 0.45f);
|
|
const float4 xmax = float4(0.15f, 0.3f, 0.45f, 0.6f);
|
|
const float tiling = 40.0;
|
|
float4 halftoneTx = TEXTURE_READ_2D( samp, 1, input.uv0 * tiling ).xyzw;
|
|
float4 halftone = halftoneTx * rectFunc(xmin, xmax, lightness);
|
|
halftone = factor * dot(halftone, float4(1,1,1,1));
|
|
halftone = 1.0f - halftone;
|
|
|
|
// Blend layers
|
|
output.clr.rgb = lerp( output.clr.rgb, clr * halftone.x, ps_reg0.x );
|
|
|
|
return output;
|
|
}
|
|
PS_OUT ps_mask_body_part(VS_OUT input)
|
|
{
|
|
float playerMask = TEXTURE_READ_2D( samp, 1, input.uv0.xy ).x;
|
|
|
|
playerMask = linStep( ps_reg2.x, ps_reg2.y, max(0,playerMask ));
|
|
float4 color = float4( TEXTURE_READ_2D( samp, 0, input.uv0 ).xyz, playerMask );
|
|
|
|
PS_OUT output;
|
|
output.clr = color;
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_body_part_hide(VS_OUT input)
|
|
{
|
|
float3 color0 = TEXTURE_READ_2D( samp, 0, ps_reg0.xy ).xyz;
|
|
float3 color1 = TEXTURE_READ_2D( samp, 0, ps_reg0.zw ).xyz;
|
|
float3 color2 = TEXTURE_READ_2D( samp, 0, ps_reg1.xy ).xyz;
|
|
float3 color3 = TEXTURE_READ_2D( samp, 0, ps_reg1.zw ).xyz;
|
|
|
|
float playerMask = TEXTURE_READ_2D( samp, 1, input.uv0 ).x;
|
|
playerMask = linStep( ps_reg2.x, ps_reg2.y, playerMask );
|
|
float4 color = float4( TEXTURE_READ_2D( samp, 0, input.uv0.xy ).xyz, playerMask );
|
|
|
|
float4 colorF = float4( ( ( color0 + color1 + color2 + color3 ) / 4.0f), playerMask );
|
|
|
|
PS_OUT output;
|
|
output.clr = lerp( color, colorF, playerMask);
|
|
//output.clr = float4(playerMask.xxx,1.0f);
|
|
|
|
return output;
|
|
}
|
|
|
|
|
|
// Perspective correction
|
|
PS_OUT ps_mask_body_part_PC(VS_PC_OUT input)
|
|
{
|
|
float2 uv = input.uv.xy / input.uv.z;
|
|
float playerMask = TEXTURE_READ_2D( samp, 1, uv ).x;
|
|
playerMask = linStep( ps_reg2.x, ps_reg2.y, playerMask );
|
|
float4 color = float4( TEXTURE_READ_2D( samp, 0, uv ).xyz, playerMask );
|
|
|
|
float2 uv2 = input.uv2.xy / input.uv2.z;
|
|
float playerMask2 = TEXTURE_READ_2D( samp, 2, uv2 ).x;
|
|
playerMask2 = linStep( ps_reg2.x, ps_reg2.y, playerMask2 );
|
|
float4 color2 = float4( TEXTURE_READ_2D( samp, 0, uv2 ).xyz, playerMask2 );
|
|
|
|
float val = 0.0f;
|
|
val += ( 1.0f - rectFunc( 0.0f, ps_reg2.z, input.uv2.w ) ) * ( 1.0f - rectFunc( ps_reg2.z, 1.0f, input.uv2.w ) ) ;
|
|
val += rectFunc( ps_reg2.z, ps_reg2.w, input.uv2.w ) * ( ( input.uv2.w - ps_reg2.z ) / ( ps_reg2.w - ps_reg2.z ) );
|
|
val += rectFunc( ps_reg2.w, 1.0f, input.uv2.w );
|
|
val = saturate(val);
|
|
|
|
PS_OUT output;
|
|
output.clr = lerp( color, color2, val );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_body_part_depth(VS_OUT input)
|
|
{
|
|
float playerMask = TEXTURE_READ_2D( samp, 1, input.uv0 ).x;
|
|
playerMask = linStep( ps_reg2.x, ps_reg2.y, playerMask );
|
|
float4 color = float4( TEXTURE_READ_2D( samp, 0, input.uv0 ).xyz, playerMask );
|
|
|
|
clip( playerMask - 1.0/255.0f );
|
|
|
|
PS_OUT output;
|
|
output.clr = color;
|
|
return output;
|
|
}
|
|
|
|
// Perspective correction
|
|
PS_OUT ps_mask_body_part_depth_PC(VS_PC_OUT input)
|
|
{
|
|
float2 uv = input.uv.xy / input.uv.z;
|
|
float playerMask = TEXTURE_READ_2D( samp, 1, uv ).x;
|
|
playerMask = linStep( ps_reg2.x, ps_reg2.y, playerMask );
|
|
float4 color = float4( TEXTURE_READ_2D( samp, 0, uv ).xyz, playerMask );
|
|
|
|
float2 uv2 = input.uv2.xy / input.uv2.z;
|
|
float playerMask2 = TEXTURE_READ_2D( samp, 2, uv2 ).x;
|
|
playerMask2 = linStep( ps_reg2.x, ps_reg2.y, playerMask2 );
|
|
float4 color2 = float4( TEXTURE_READ_2D( samp, 0, uv2 ).xyz, playerMask2 );
|
|
|
|
float val = 0.0f;
|
|
val += ( 1.0f - rectFunc( 0.0f, ps_reg2.z, input.uv2.w ) ) * ( 1.0f - rectFunc( ps_reg2.z, 1.0f, input.uv2.w ) ) ;
|
|
val += rectFunc( ps_reg2.z, ps_reg2.w, input.uv2.w ) * ( ( input.uv2.w - ps_reg2.z ) / ( ps_reg2.w - ps_reg2.z ) );
|
|
val += rectFunc( ps_reg2.w, 1.0f, input.uv2.w );
|
|
val = saturate(val);
|
|
|
|
float4 colorRes = lerp( color, color2, val );
|
|
clip( colorRes.w - 1.0/255.0f );
|
|
|
|
PS_OUT output;
|
|
output.clr = colorRes;
|
|
return output;
|
|
}
|
|
|
|
#define BODY_PART_HEAD 1.0f
|
|
#define BODY_PART_HAND_LEFT 2.0f
|
|
#define BODY_PART_HAND_RIGHT 3.0f
|
|
#define BODY_PART_FOOT_LEFT 4.0f
|
|
#define BODY_PART_FOOT_RIGHT 5.0f
|
|
#define BODY_PART_MAX BODY_PART_FOOT_RIGHT
|
|
#define BODY_PART_MARGIN 0.5f / BODY_PART_MAX
|
|
|
|
float isPart( float partIndex, float bodyPart )
|
|
{
|
|
return rectFunc( bodyPart - BODY_PART_MARGIN, bodyPart + BODY_PART_MARGIN, partIndex );
|
|
}
|
|
|
|
PS_OUT ps_mask_body_part_index(VS_OUT input)
|
|
{
|
|
float playerMask = TEXTURE_READ_2D( samp, 0, input.uv0 ).x;
|
|
|
|
#if defined DX11_SHADERS || defined DX12_SHADERS
|
|
if( ps_alphaTest.x )
|
|
{
|
|
clip( playerMask - ps_alphaTest.y );
|
|
}
|
|
#endif
|
|
|
|
PS_OUT output;
|
|
output.clr = ps_reg2.x / BODY_PART_MAX;
|
|
output.clr.a = playerMask;
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_body_part_index_PC(VS_PC_OUT input)
|
|
{
|
|
float2 uv = input.uv.xy / input.uv.z;
|
|
float playerMask = TEXTURE_READ_2D( samp, 0, uv ).x;
|
|
|
|
#if defined DX11_SHADERS || defined DX12_SHADERS
|
|
if( ps_alphaTest.x )
|
|
{
|
|
clip( playerMask - ps_alphaTest.y );
|
|
}
|
|
#endif
|
|
|
|
PS_OUT output;
|
|
output.clr = ps_reg2.x / BODY_PART_MAX;
|
|
output.clr.a = playerMask;
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_update_lightness( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
|
|
float3 clr = TEXTURE_READ_2D( samp, 0, input.uv0 ).rgb;
|
|
float4 lightPrev = TEXTURE_READ_2D( samp, 1, input.uv0 );
|
|
|
|
float3 hsl = rgb_to_hsl( clr );
|
|
|
|
float4 lightNew = hsl.z;
|
|
|
|
output.clr = lerp( lightPrev, lightNew, ps_reg0 );
|
|
|
|
return output;
|
|
}
|
|
|
|
// NuiToWorld (see DepthVisualizer example)
|
|
float3 NuiToWorld( float3 vNuiPosition )
|
|
{
|
|
float3 vWorldPosition;
|
|
|
|
vWorldPosition.xy = vNuiPosition.z * ps_reg0.xy * ( vNuiPosition.xy - 0.5f );
|
|
vWorldPosition.z = vNuiPosition.z;
|
|
|
|
return vWorldPosition;
|
|
}
|
|
|
|
// Normal Map
|
|
PS_OUT ps_normal_map(VS_OUT input)
|
|
{
|
|
float4 depths = float4(
|
|
TEXTURE_READ_2D( samp, 0, input.uv0 ).r,
|
|
TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, 0.0 ) ).r,
|
|
TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, ps_samp0Size.w ) ).r,
|
|
1.0f );
|
|
|
|
// Recover the 3 worldspace sample coordinates
|
|
float3 vWorld00 = NuiToWorld( float3( input.uv0, depths.x ) );
|
|
float3 vWorld10 = NuiToWorld( float3( input.uv0 + float2( ps_samp0Size.z, 0.0 ), depths.y ) );
|
|
float3 vWorld01 = NuiToWorld( float3( input.uv0 + float2( 0.0, ps_samp0Size.w ), depths.z ) );
|
|
|
|
// From the change in depth in the x and the y direction, compute the viewspace normal vector
|
|
float3 vTangent = vWorld10 - vWorld00;
|
|
float3 vBinormal = vWorld01 - vWorld00;
|
|
float3 vNormal = normalize( cross( vTangent, vBinormal ) );
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( vNormal * 0.5f + 0.5f, 1.0f );
|
|
return output;
|
|
}
|
|
|
|
// Bilateral depth filter
|
|
|
|
#define KER_HALFSIZE 3 // Fixed kernel size
|
|
#define KER_DIRECTION ps_reg0.xy
|
|
#define BILATERAL_ATT ps_reg0.z
|
|
#define KER_WEIGHTS ps_reg1
|
|
|
|
PS_OUT ps_filter_depth(VS_OUT input)
|
|
{
|
|
// Construct weights
|
|
float vWeights[ KER_HALFSIZE * 2 + 1 ] = { KER_WEIGHTS.w, KER_WEIGHTS.z, KER_WEIGHTS.y, KER_WEIGHTS.x, KER_WEIGHTS.y, KER_WEIGHTS.z, KER_WEIGHTS.w };
|
|
|
|
// Take samples
|
|
|
|
float vSamples[ KER_HALFSIZE * 2 + 1 ];
|
|
for (int i = -KER_HALFSIZE; i <= KER_HALFSIZE; ++i)
|
|
{
|
|
float2 uvOffset = KER_DIRECTION * ps_samp0Size.zw * i;
|
|
vSamples[ KER_HALFSIZE + i ] = TEXTURE_READ_2D( samp, 0, input.uv0 + uvOffset ).r;
|
|
}
|
|
|
|
// Average them taking edges into account
|
|
|
|
float fCenterDepth = vSamples[KER_HALFSIZE];
|
|
|
|
float fDepthWeighted = 0.0f;
|
|
float fTotalWeight = 0.0f;
|
|
|
|
float denormalize = 1.0f;
|
|
#ifdef ITF_DURANGO
|
|
denormalize = 3500.0f;
|
|
#endif
|
|
|
|
for (int i = -KER_HALFSIZE; i <= KER_HALFSIZE; ++i)
|
|
{
|
|
float fDepth = vSamples[ KER_HALFSIZE + i ];
|
|
float fWeight = vWeights[ KER_HALFSIZE + i ];
|
|
float fDepthDist = fCenterDepth - fDepth;
|
|
float fFalloff = exp2( -BILATERAL_ATT * fDepthDist * denormalize * fDepthDist * denormalize );
|
|
fWeight *= fFalloff;
|
|
fDepthWeighted += fWeight * fDepth;
|
|
fTotalWeight += fWeight;
|
|
}
|
|
|
|
PS_OUT output;
|
|
output.clr = fDepthWeighted / fTotalWeight;
|
|
return output;
|
|
}
|
|
|
|
#undef KER_DIRECTION
|
|
#undef KER_HALFSIZE
|
|
#undef KER_WEIGHTS
|
|
#undef BILATERAL_ATT
|
|
|
|
#define KER_HALFSIZE 3 // Fixed kernel size
|
|
#define KER_DIRECTION ps_reg0.xy
|
|
#define KER_WEIGHTS ps_reg1
|
|
|
|
PS_OUT ps_filter_mask(VS_OUT input)
|
|
{
|
|
// Construct weights
|
|
float vWeights[ KER_HALFSIZE * 2 + 1 ] = { KER_WEIGHTS.w, KER_WEIGHTS.z, KER_WEIGHTS.y, KER_WEIGHTS.x, KER_WEIGHTS.y, KER_WEIGHTS.z, KER_WEIGHTS.w };
|
|
|
|
// Take samples
|
|
|
|
float vSamples[ KER_HALFSIZE * 2 + 1 ];
|
|
for (int i = -KER_HALFSIZE; i <= KER_HALFSIZE; ++i)
|
|
{
|
|
float2 uvOffset = KER_DIRECTION * ps_samp0Size.zw * i;
|
|
vSamples[ KER_HALFSIZE + i ] = TEXTURE_READ_2D( samp, 0, input.uv0 + uvOffset ).r;
|
|
}
|
|
|
|
// Average them taking edges into account
|
|
|
|
float fMaskWeighted = 0.0f;
|
|
float fTotalWeight = 0.0f;
|
|
|
|
for (int i = -KER_HALFSIZE; i <= KER_HALFSIZE; ++i)
|
|
{
|
|
float3 fClr = vSamples[ KER_HALFSIZE + i ];
|
|
float fWeight = vWeights[ KER_HALFSIZE + i ];
|
|
fMaskWeighted += fWeight * fClr;
|
|
fTotalWeight += fWeight;
|
|
}
|
|
|
|
float fRes = fMaskWeighted / fTotalWeight;
|
|
|
|
PS_OUT output;
|
|
output.clr = fRes;
|
|
return output;
|
|
}
|
|
|
|
#undef KER_DIRECTION
|
|
#undef KER_HALFSIZE
|
|
#undef KER_WEIGHTS
|
|
|
|
PS_OUT ps_refraction(VS_OUT input)
|
|
{
|
|
float2 normal = TEXTURE_READ_2D( samp, 2, input.uv0 ).xy;
|
|
normal = ( normal * 2.0f ) - 1.0f;
|
|
|
|
float2 refractTexCoord = input.uv0 + ( normal.xy * ps_reg0.xy );
|
|
|
|
float4 iceColor = float4( TEXTURE_READ_2D( samp, 1, input.uv0 ).xyz * ps_reg1.xyz, 1.0f );
|
|
float4 refractedColor = TEXTURE_READ_2D( samp, 0, refractTexCoord );
|
|
|
|
float4 cleanColor = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float4 refractionResult = float4( lerp(refractedColor, iceColor, ps_reg0.z).xyz, cleanColor.w );
|
|
|
|
PS_OUT output;
|
|
output.clr = lerp( cleanColor, refractionResult, ps_reg0.w);
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_alpha_gradient(VS_OUT input)
|
|
{
|
|
float min = ps_reg0.x;
|
|
float max = ps_reg0.y;
|
|
|
|
float4 vOrigColor = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float fAlpha = clamp(((1.0f-input.uv0.y) - min) / (max-min), 0.0f, 1.0f);
|
|
|
|
PS_OUT output;
|
|
output.clr = float4(vOrigColor.rgb, fAlpha * vOrigColor.a);
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_colored_shiva_alpha_blend( VS_OUT input )
|
|
{
|
|
float4 oldImage = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float4 newImage = TEXTURE_READ_2D( samp, 1, input.uv0 );
|
|
|
|
float finalAlpha = newImage.w +( oldImage.w*( 1.0-newImage.w ) );
|
|
float3 finalClr =( newImage.xyz * newImage.w ) +( oldImage.xyz*oldImage.w*( 1.0-newImage.w ) );
|
|
finalClr /= finalAlpha + 0.001f;
|
|
|
|
if( newImage.w >= ps_reg0.x && newImage.w < ps_reg0.y )
|
|
{
|
|
finalClr = lerp( finalClr, ps_reg1.xyz, ps_reg1.w );
|
|
}
|
|
else if( newImage.w >= ps_reg0.y && newImage.w < ps_reg0.z )
|
|
{
|
|
finalClr = lerp( finalClr, ps_reg2.xyz, ps_reg2.w );
|
|
}
|
|
else if( newImage.w >= ps_reg0.z && newImage.w < ps_reg0.w )
|
|
{
|
|
finalClr = lerp( finalClr, ps_reg3.xyz, ps_reg3.w );
|
|
}
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( finalClr, finalAlpha );
|
|
return output;
|
|
}
|
|
|
|
float GetShivaAlpha(float2 uv)
|
|
{
|
|
return TEXTURE_READ_2D( samp, 0, uv ).a;
|
|
}
|
|
|
|
float4 GetShivaColourFromAlpha(float alpha,float alphaDelta,float4 defaultCol)
|
|
{
|
|
float finalAlpha = alpha;//max(alpha,alphaDelta);
|
|
float3 finalClr = defaultCol * alpha;
|
|
finalClr = lerp(ps_reg1.xyz,finalClr,finalAlpha);
|
|
|
|
if( alpha >= ps_reg0.x && alpha < ps_reg0.y )
|
|
{
|
|
finalClr = lerp( finalClr, ps_reg1.xyz, ps_reg1.w );
|
|
}
|
|
else if( alpha >= ps_reg0.y && alpha < ps_reg0.z )
|
|
{
|
|
finalClr = lerp( finalClr, ps_reg2.xyz, ps_reg2.w );
|
|
}
|
|
else if( alpha >= ps_reg0.z && alpha < ps_reg0.w )
|
|
{
|
|
finalClr = lerp( finalClr, ps_reg3.xyz, ps_reg3.w );
|
|
}
|
|
|
|
return float4(RGB2XYY(finalClr),alpha);
|
|
}
|
|
|
|
float4 GetShivaColour(float2 uv)
|
|
{
|
|
float4 newImage = TEXTURE_READ_2D( samp, 0, uv );
|
|
|
|
float finalAlpha = newImage.w;
|
|
float3 finalClr = newImage.xyz * newImage.w;
|
|
finalClr = lerp(ps_reg1.xyz,finalClr,finalAlpha);
|
|
|
|
if( newImage.w >= ps_reg0.x && newImage.w < ps_reg0.y )
|
|
{
|
|
finalClr = lerp( finalClr, ps_reg1.xyz, ps_reg1.w );
|
|
//finalAlpha = ps_reg1.w;
|
|
}
|
|
else if( newImage.w >= ps_reg0.y && newImage.w < ps_reg0.z )
|
|
{
|
|
finalClr = lerp( finalClr, ps_reg2.xyz, ps_reg2.w );
|
|
//finalAlpha = ps_reg2.w;
|
|
}
|
|
else if( newImage.w >= ps_reg0.z && newImage.w < ps_reg0.w )
|
|
{
|
|
finalClr = lerp( finalClr, ps_reg3.xyz, ps_reg3.w );
|
|
//finalAlpha = ps_reg3.w;
|
|
}
|
|
|
|
return float4(RGB2XYY(finalClr),finalAlpha);
|
|
}
|
|
|
|
PS_OUT ps_colored_shiva( VS_OUT input )
|
|
{
|
|
float ou = ddx(input.uv0.x) * 1.5f;
|
|
float ov = ddy(input.uv0.y) * 1.5f;
|
|
|
|
float3 baseColour = RGB2XYY(TEXTURE_READ_2D( samp, 0, input.uv0 ).rgb);
|
|
float4 colcc = GetShivaColour(input.uv0);
|
|
|
|
float alpha00 = GetShivaAlpha(input.uv0 + float2(-ou,0));
|
|
float alpha10 = GetShivaAlpha(input.uv0 + float2(ou,0));
|
|
float alpha11 = GetShivaAlpha(input.uv0 + float2(0,ov));
|
|
float alpha01 = GetShivaAlpha(input.uv0 + float2(0,-ov));
|
|
|
|
float alphaDelta = max(abs(alpha01 - alpha00),abs(alpha11 - alpha10));
|
|
float alphaSum = alpha00 + alpha10 + alpha11 + alpha01 + colcc.a;
|
|
float alphaMax = max(max(max(max(alpha00,alpha10),alpha11),alpha01),colcc.a);
|
|
|
|
float4 col00 = GetShivaColourFromAlpha(alpha00,alphaDelta,colcc);
|
|
float4 col10 = GetShivaColourFromAlpha(alpha10,alphaDelta,colcc);
|
|
float4 col11 = GetShivaColourFromAlpha(alpha11,alphaDelta,colcc);
|
|
float4 col01 = GetShivaColourFromAlpha(alpha01,alphaDelta,colcc);
|
|
|
|
float4 finalClr = (col01 + col11 + col10 + col00 + colcc) * 0.2f;
|
|
|
|
float blend = saturate((finalClr.a - 0.85f) * 10.0f);
|
|
|
|
finalClr.rgb = XYY2RGB(lerp(finalClr.rgb,baseColour.rgb,blend));
|
|
finalClr.a = saturate((finalClr.a - alphaDelta) * 10.0f);
|
|
|
|
PS_OUT output;
|
|
output.clr = finalClr;
|
|
|
|
return output;
|
|
}
|
|
|
|
// Saturation
|
|
PS_OUT ps_saturation( VS_OUT input )
|
|
{
|
|
float4 sourceColor = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float3 sourceColorHSL = rgb_to_hsl( sourceColor );
|
|
sourceColorHSL.y = clamp( sourceColorHSL.y + ps_reg0.x, 0.0f, 1.0f );
|
|
float3 modifiedColor = hsl_to_rgb( sourceColorHSL );
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( modifiedColor, sourceColor.w );
|
|
return output;
|
|
}
|
|
|
|
// Ghostbusters Slime Effect
|
|
|
|
// .. Get downward player edges
|
|
PS_OUT ps_slime_mask_p0(VS_OUT input)
|
|
{
|
|
float clr_0 = saturate(TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, -ps_samp0Size.w *ps_reg0.x) ).r);
|
|
float clr_1 = saturate(TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, -ps_samp0Size.w *ps_reg0.x*2 ) ).r);
|
|
float clr_2 = saturate(TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, ps_samp0Size.w *ps_reg0.x ) ).r);
|
|
float clr_3 = saturate(TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, ps_samp0Size.w *ps_reg0.x*2 ) ).r);
|
|
|
|
float fRes = step( 1.5f, ( clr_2 + clr_3 - clr_0 - clr_1 ) );
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( fRes, fRes, fRes, 1.0f );
|
|
return output;
|
|
}
|
|
|
|
// .. Get upward normals
|
|
PS_OUT ps_slime_mask_p1(VS_OUT input)
|
|
{
|
|
float3 normal = TEXTURE_READ_2D( samp, 0, input.uv0 ).rgb * 2.0f - 1.0f;
|
|
|
|
float fRes = step( ps_reg0.y, normal.y );
|
|
|
|
PS_OUT output;
|
|
|
|
output.clr = float4( fRes, fRes, fRes, 1.0f );
|
|
|
|
return output;
|
|
}
|
|
|
|
// .. Drip
|
|
PS_OUT ps_slime_mask_drip(VS_OUT input)
|
|
{
|
|
float clr_c = saturate(TEXTURE_READ_2D( samp, 0, input.uv0 ).r);
|
|
float clr_0 = saturate(TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, -ps_samp0Size.w ) ).r);
|
|
float clr_1 = saturate(TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, -ps_samp0Size.w * 2 ) ).r);
|
|
float clr_2 = saturate(TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, -ps_samp0Size.w * 3 ) ).r);
|
|
float clr_3 = saturate(TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, -ps_samp0Size.w * 4 ) ).r);
|
|
|
|
float2 uv = ( input.uv0 - float2( 0.0f, 0.75f ) ) / float2( 0.25f, 0.25f );
|
|
float partIndex = TEXTURE_READ_2D( samp, 1, uv ).r * BODY_PART_MAX;
|
|
|
|
float fRes = ceil( ( clr_c.x + clr_0 + clr_1 + clr_2 + clr_3 ) / 5.0f );
|
|
|
|
// Do not drip if head
|
|
fRes = lerp( fRes, clr_c, isPart(partIndex, BODY_PART_HEAD) );
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( fRes, fRes, fRes, 1.0f );
|
|
return output;
|
|
}
|
|
|
|
// .. Slime
|
|
|
|
#define SLIME_FACTOR ps_reg0.x
|
|
#define SLIME_COLOR ps_reg0.gba
|
|
#define NORMAL_TILING ps_reg1.xy
|
|
#define LIGHT_ANGLE_X ps_reg1.z
|
|
#define LIGHT_ANGLE_Z ps_reg1.w
|
|
#define REFRACTION_AMOUNT ps_reg2.x
|
|
#define REFRACTION_INDEX ps_reg2.y
|
|
#define SPECULAR_AMOUNT ps_reg2.z
|
|
#define SPECULAR_POWER ps_reg2.w
|
|
#define SLIME_AMBIENT ps_reg3.x
|
|
#define SLIME_OPACITY ps_reg3.y
|
|
|
|
PS_OUT ps_slime(VS_OUT input)
|
|
{
|
|
const float3 down = float3(0.0f, -1.0f, 0.0f);
|
|
const float3 toEye = float3(0,0,-1);
|
|
|
|
float3 normal = TEXTURE_READ_2D( samp, 1, input.uv0 ).rgb * 2.0f - 1.0f;
|
|
float3 normalDistortion = TEXTURE_READ_2D( samp, 2, input.uv0 * NORMAL_TILING ).rbg * 2.0f - 1.0f;
|
|
|
|
// Transform normal
|
|
|
|
float3 tg = cross(normal, down);
|
|
float3 binormal = cross(normal, tg);
|
|
tg = cross(binormal, normal);
|
|
|
|
float3x3 tgToWorld = float3x3(
|
|
float3(tg.x, tg.y, tg.z),
|
|
float3(normal.x, normal.y, normal.z),
|
|
float3(binormal.x, binormal.y, binormal.z ));
|
|
|
|
float3 newNormal = normalize( mul( normalDistortion, tgToWorld ) );
|
|
|
|
// Compute the reflection vector.
|
|
float3 gLightVecW = float3( LIGHT_ANGLE_X, 0.0f, LIGHT_ANGLE_Z );
|
|
gLightVecW = normalize(gLightVecW);
|
|
float3 vReflect = reflect(gLightVecW, newNormal);
|
|
|
|
// Specular light
|
|
float spec = pow(max(dot(vReflect, toEye), 0.0f), SPECULAR_POWER);
|
|
|
|
// Refraction
|
|
float3 vRefract = refract(-toEye, newNormal, REFRACTION_INDEX) * REFRACTION_AMOUNT;
|
|
float2 uvRefract = vRefract.xy;
|
|
|
|
// Refracted color
|
|
float4 clrSrc = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float4 clrRefr = TEXTURE_READ_2D( samp, 0, input.uv0 + uvRefract );
|
|
clrRefr.rgb = lerp( clrSrc.rgb, clrRefr.rgb, clrRefr.a );
|
|
|
|
// Final color
|
|
float3 vAmbient = SLIME_COLOR * SLIME_AMBIENT;
|
|
float3 vDiffuse = SLIME_COLOR;// * dot(newNormal, -gLightVecW);
|
|
float3 vTransmitted = clrRefr.rgb * SLIME_COLOR;
|
|
float3 vSpecular = (spec * SLIME_COLOR) * SPECULAR_AMOUNT;
|
|
float3 finalClr = vAmbient +
|
|
lerp( vTransmitted, vDiffuse, SLIME_OPACITY ) +
|
|
vSpecular;
|
|
|
|
PS_OUT output;
|
|
|
|
output.clr = float4( lerp( clrSrc.rgb, finalClr, SLIME_FACTOR ), clrSrc.a );
|
|
|
|
return output;
|
|
}
|
|
|
|
#undef SLIME_FACTOR
|
|
#undef SLIME_COLOR
|
|
#undef NORMAL_TILING
|
|
#undef LIGHT_ANGLE_X
|
|
#undef LIGHT_ANGLE_Z
|
|
#undef REFRACTION_AMOUNT
|
|
#undef REFRACTION_INDEX
|
|
#undef SPECULAR_AMOUNT
|
|
#undef SPECULAR_POWER
|
|
|
|
PS_OUT ps_replace_color_pow_alpha( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
float alpha = TEXTURE_READ_2D( samp, 0, input.uv0 ).a;
|
|
output.clr = float4(ps_reg0.xyz, pow(alpha, ps_reg0.w));
|
|
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_replace_tex_pow_alpha( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
float alpha = TEXTURE_READ_2D( samp, 0, input.uv0 ).a;
|
|
float4 clr = TEXTURE_READ_2D( samp, 1, input.uv0 * ps_reg0.zz ).rgba;
|
|
output.clr = float4(clr.rgb, clr.a * pow(alpha, ps_reg0.x) * ps_reg0.y );
|
|
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_overlay_grayscale_color( VS_OUT input )
|
|
{
|
|
DEFINE_CONSTANTS;
|
|
|
|
PS_OUT output;
|
|
|
|
float4 color = float4(0.0f, 0.0f, 0.0f, 1.0f);
|
|
|
|
float3 bcolor = ps_reg0.xyz;
|
|
float3 acolor = TEXTURE_READ_2D( samp, 1, input.uv0 ).xyz;
|
|
|
|
float4 sourceColor = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
|
|
float k = saturate(ceil(0.5f - acolor.r));
|
|
|
|
color.rgb = lerp( (2.0f*acolor*bcolor), (vec3_one - 2.0f*(vec3_one - acolor)*( vec3_one - bcolor)), k);
|
|
|
|
#if !defined DX11_SHADERS && !defined DX12_SHADERS
|
|
//Revert gamma correction on 360
|
|
color.rgb = pow(color.rgb, 2.2);
|
|
#endif
|
|
|
|
output.clr = lerp(sourceColor, color, ps_reg0.w);
|
|
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_overlay_grayscale_color_2( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
|
|
float4 color = float4(0.0f, 0.0f, 0.0f, 1.0f);
|
|
|
|
const float3 vec3_one = float3(1.0f,1.0f,1.0f);
|
|
const float3 vec3_zero = float3(0.0f,0.0f,0.0f);
|
|
|
|
float4 sourceColor = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
|
|
float l = 0;
|
|
float2 MinMax;
|
|
|
|
MinMax.x = min( sourceColor.r, min(sourceColor.g, sourceColor.b) );
|
|
MinMax.y = max( sourceColor.r, max(sourceColor.g, sourceColor.b) );
|
|
|
|
l = 0.5 * (MinMax.x + MinMax.y);
|
|
|
|
float3 bcolor = ps_reg1.xyz;
|
|
float3 acolor = float3(l,l,l);
|
|
|
|
float k = saturate(ceil(0.5f - l));
|
|
|
|
float3 overlayBelnded = lerp( (2.0f*acolor*bcolor), (vec3_one - 2.0f*(vec3_one - acolor)*( vec3_one - bcolor)), k);
|
|
|
|
output.clr = float4(lerp(sourceColor.rgb, overlayBelnded, ps_reg1.w), sourceColor.a);
|
|
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_lerp_copy_as_is( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
output.clr = lerp( TEXTURE_READ_2D( samp, 0, input.uv0 ), TEXTURE_READ_2D( samp, 1, input.uv0 ), ps_reg0.x );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_tint_mul_color( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
|
|
float4 color = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float3 colorTint = ps_reg1.xyz;
|
|
|
|
float l = 0;
|
|
float2 MinMax;
|
|
|
|
MinMax.x = min( color.r, min(color.g, color.b) );
|
|
MinMax.y = max( color.r, max(color.g, color.b) );
|
|
|
|
l = 0.5 * (MinMax.x + MinMax.y);
|
|
|
|
output.clr = lerp(color, float4( colorTint * l, color.a), ps_reg0.x );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_particles( VS_Particle_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
float2 texUV = input.uv;
|
|
float4 texCol = TEXTURE_READ_2D( samp, 0, texUV );
|
|
texCol.a = dot(texCol.rgb,float3(0.299f, 0.587f, 0.114f));
|
|
|
|
output.clr = input.uv2 * texCol;
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_lobbytoy_explode( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
|
|
output.clr = float4(0,0,0,0);
|
|
|
|
float fPerc = ps_reg0.x;
|
|
|
|
float2 vDir = float2(0.5, 0.5) - input.uv0;
|
|
|
|
float2 vExplode = vDir * fPerc;
|
|
float2 vSrc = input.uv0 + vExplode;
|
|
|
|
output.clr = TEXTURE_READ_2D(samp, 0, vSrc);;
|
|
|
|
return output;
|
|
}
|
|
|
|
// ---------------------------------------Player Mask --------------------------------------
|
|
|
|
// Buffers info
|
|
//
|
|
// Body info: ( Mask, MaxDilation, IgnoreHoles, MaxSize )
|
|
// DilatedMask: ( Mask Dilated, MaxDilation Dilated, ", Mask Original )
|
|
// Shrink: ( Mask Shrinked, ", Mask Dilated, Mask Original )
|
|
// Fill color: ( Mask Filling, Color rgb for comparison )
|
|
// Fill Holes: ( Mask Filling, MaxDilation Dilated, Mask Dilated, Dilation Count )
|
|
//
|
|
|
|
// Body part info
|
|
|
|
#ifdef ITF_DURANGO
|
|
#define DILATION_MAX 4.0f
|
|
#define DILATION_HEAD 4.0f
|
|
#define DILATION_HANDS 2.0f
|
|
#define DILATION_FEET 2.0f
|
|
#else
|
|
#define DILATION_MAX 6.0f
|
|
#define DILATION_HEAD 6.0f
|
|
#define DILATION_HANDS 3.0f
|
|
#define DILATION_FEET 3.0f
|
|
#endif
|
|
#define DILATION_NORM (1.0f / DILATION_MAX)
|
|
|
|
// Player Utility functions
|
|
|
|
#define GET_NEIGHBORHOOD_INFO \
|
|
float4 mask_t = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, -ps_samp0Size.w ) ).xyzw; \
|
|
float4 mask_l = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z, 0.0 ) ).xyzw; \
|
|
float4 mask_c = TEXTURE_READ_2D( samp, 0, input.uv0 ).xyzw; \
|
|
float4 mask_r = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, 0.0 ) ).xyzw; \
|
|
float4 mask_b = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, ps_samp0Size.w ) ).xyzw; \
|
|
float isMask = ceil(mask_c.x); \
|
|
float4 neighbors_x = float4( mask_l.x, mask_r.x, mask_t.x, mask_b.x ); \
|
|
float4 neighbors_y = float4( mask_l.y, mask_r.y, mask_t.y, mask_b.y ); \
|
|
float4 neighbors_z = float4( mask_l.z, mask_r.z, mask_t.z, mask_b.z ); \
|
|
float4 neighbors_w = float4( mask_l.w, mask_r.w, mask_t.w, mask_b.w );
|
|
|
|
#define GET_NEIGHBORHOOD_INFO_EX \
|
|
float4 mask_tt = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, -ps_samp0Size.w * 2 ) ).xyzw; \
|
|
float4 mask_ll = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z * 2, 0.0 ) ).xyzw; \
|
|
float4 mask_rr = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z * 2, 0.0 ) ).xyzw; \
|
|
float4 mask_bb = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, ps_samp0Size.w * 2 ) ).xyzw; \
|
|
float4 neighborsEx_x = float4( mask_ll.x, mask_rr.x, mask_tt.x, mask_bb.x ); \
|
|
float4 neighborsEx_y = float4( mask_ll.y, mask_rr.y, mask_tt.y, mask_bb.y ); \
|
|
float4 neighborsEx_z = float4( mask_ll.z, mask_rr.z, mask_tt.z, mask_bb.z ); \
|
|
float4 neighborsEx_w = float4( mask_ll.w, mask_rr.w, mask_tt.w, mask_bb.w );
|
|
|
|
inline float Neighborhood_SamePlayers( float mask_c, float4 mask_neighbors )
|
|
{
|
|
float fPlayerIdxMax = Max( mask_c, mask_neighbors );
|
|
float fPlayersCount = ceil(mask_c) + Sum( ceil(mask_neighbors) );
|
|
float fPlayerIdxAvg = ( mask_c + Sum( mask_neighbors ) ) / fPlayersCount;
|
|
|
|
return step( abs( fPlayerIdxMax - fPlayerIdxAvg ), EPSILON );
|
|
}
|
|
|
|
inline float Neighborhood_CommonPlayerIdx( float mask_c, float4 mask_neighbors )
|
|
{
|
|
float samePlayers = Neighborhood_SamePlayers( mask_c, mask_neighbors );
|
|
float fPlayerIdxMax = Max( mask_c.x, mask_neighbors );
|
|
|
|
return samePlayers * fPlayerIdxMax;
|
|
}
|
|
|
|
inline float Neighborhood_AllMask( float mask_c, float4 mask_neighbors )
|
|
{
|
|
return ITF_ALL2( float2( mask_c, ITF_ALL2( mask_neighbors ) ) );
|
|
}
|
|
|
|
inline float Neighborhood_AnyMask( float mask_c, float4 mask_neighbors )
|
|
{
|
|
return ITF_ANY2( float2( mask_c, ITF_ANY2( mask_neighbors ) ) );
|
|
}
|
|
|
|
float Neighborhood_SameRegions( float4 mask_neighbors, float4 mask_neighborsEx )
|
|
{
|
|
float4 v1 = float4( mask_neighbors.x, mask_neighborsEx.x, mask_neighbors.y, mask_neighborsEx.y );
|
|
float4 v2 = float4( mask_neighbors.z, mask_neighborsEx.z, mask_neighbors.w, mask_neighborsEx.w );
|
|
|
|
float4 maskTexels1 = ceil(v1);
|
|
float4 maskTexels2 = ceil(v2);
|
|
|
|
float maskTexelsCount = Sum( maskTexels1 + maskTexels2 );
|
|
float maskTexels = Sum( v1 + v2 );
|
|
|
|
float maskTexelsAvg = maskTexels / maskTexelsCount;
|
|
|
|
float4 maskTexelsDiff1 = step( EPSILON, abs( v1 - maskTexels1 * maskTexelsAvg ) );
|
|
float4 maskTexelsDiff2 = step( EPSILON, abs( v2 - maskTexels2 * maskTexelsAvg ) );
|
|
|
|
return 1.0f - saturate( float( ITF_ANY4( maskTexelsDiff1 ) + ITF_ANY4( maskTexelsDiff2 ) ) );
|
|
}
|
|
|
|
// CMA (Cumulative Movement Average Buffer)
|
|
|
|
PS_OUT ps_cma_copy( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
output.clr.rgb = TEXTURE_READ_2D( samp, 0, input.uv0 ).rgb;
|
|
output.clr.a = 1.0f; // Set pixel invalid
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_cma( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
|
|
output.clr = TEXTURE_READ_2D( samp, 0, input.uv0 ).rgba;
|
|
float3 clr = TEXTURE_READ_2D( samp, 1, input.uv0 ).rgb;
|
|
#ifdef ITF_DURANGO
|
|
float playerMask = ceil( TEXTURE_READ_2D( samp, 2, input.uv0 ).x );
|
|
#else
|
|
float playerMask = ceil( TEXTURE_READ_2D( samp, 2, input.uv0 ).y );
|
|
#endif
|
|
|
|
float3 cma = output.clr.rgb;
|
|
|
|
// If the pixel has never been written (invalid), we will write the clr completely
|
|
float bgFactor = max( ps_reg0.x, output.clr.a );
|
|
|
|
// Accumulate only background
|
|
output.clr.rgb = lerp( lerp( cma, clr, bgFactor ), cma, playerMask );
|
|
|
|
// Set valid pixel
|
|
output.clr.a = min( output.clr.a, playerMask );
|
|
|
|
return output;
|
|
}
|
|
|
|
// Edge Diff
|
|
|
|
PS_OUT ps_edge_diff_intensity(VS_OUT input)
|
|
{
|
|
DEFINE_CONSTANTS;
|
|
|
|
float3 clr = TEXTURE_READ_2D( samp, 0, input.uv0 ).rgb;
|
|
float4 cma = TEXTURE_READ_2D( samp, 1, input.uv0 ).rgba;
|
|
|
|
float fClrI = dot( rgb_to_y, clr.rgb );
|
|
float fCmaI = dot( rgb_to_y, cma.rgb );
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( fClrI, fCmaI, cma.a, 1.0f );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_edge_diff_blur(VS_OUT input)
|
|
{
|
|
float2 fRes = 0;
|
|
|
|
float3 img_c = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0, 0 ) ).xyz;
|
|
|
|
fRes += TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z, -ps_samp0Size.w ) ).xy * 0.07511f;
|
|
fRes += TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0, -ps_samp0Size.w ) ).xy * 0.12384f;
|
|
fRes += TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, -ps_samp0Size.w ) ).xy * 0.07511f;
|
|
fRes += TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z, 0 ) ).xy * 0.12384f;
|
|
fRes += img_c.xy * 0.20418f;
|
|
fRes += TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, 0 ) ).xy * 0.12384f;
|
|
fRes += TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z, ps_samp0Size.w ) ).xy * 0.07511f;
|
|
fRes += TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0, ps_samp0Size.w ) ).xy * 0.12384f;
|
|
fRes += TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, ps_samp0Size.w ) ).xy * 0.07511f;
|
|
|
|
PS_OUT output;
|
|
output.clr = float4(fRes, img_c.z, 1.0f);
|
|
return output;
|
|
}
|
|
|
|
// Canny Edge detection
|
|
|
|
PS_OUT ps_edge_diff_canny_gradient( VS_OUT input )
|
|
{
|
|
float2 img_00 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z, -ps_samp0Size.w ) ).xy;
|
|
float2 img_01 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0, -ps_samp0Size.w ) ).xy;
|
|
float2 img_02 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, -ps_samp0Size.w ) ).xy;
|
|
float2 img_10 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z, 0 ) ).xy;
|
|
float2 img_12 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, 0 ) ).xy;
|
|
float2 img_20 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z, ps_samp0Size.w ) ).xy;
|
|
float2 img_21 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0, ps_samp0Size.w ) ).xy;
|
|
float2 img_22 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, ps_samp0Size.w ) ).xy;
|
|
|
|
float2 fGradIntensityX = img_02 + 2.0f * img_12 + img_22 - img_00 - 2.0f * img_10 - img_20;
|
|
float2 fGradIntensityY = img_00 + 2.0f * img_01 + img_02 - img_20 - 2.0f * img_21 - img_22;
|
|
float2 fGradIntensity = abs(fGradIntensityX) + abs(fGradIntensityY);
|
|
float2 fGradDir = atan2( fGradIntensityY, fGradIntensityX );
|
|
|
|
// Invalid cma
|
|
float valid = 1.0f - TEXTURE_READ_2D( samp, 0, input.uv0 ).z;
|
|
fGradIntensity.y *= valid;
|
|
fGradDir.y *= valid;
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( fGradIntensity / 4.0f, (fGradDir / PI) * 0.5f + 0.5f );
|
|
return output;
|
|
}
|
|
|
|
float2 IsDirection(float2 angle1, float2 angle2, float direction)
|
|
{
|
|
const float DIRECTION_GROUP_SIZE = 1.0f / 4.0f;
|
|
const float DIRECTION_GROUP_OFFSET = 1.0f / 16.0f;
|
|
float2 g1 = floor( frac(2.0 * (angle1 + DIRECTION_GROUP_OFFSET)) / DIRECTION_GROUP_SIZE );
|
|
float2 g2 = floor( frac(2.0 * (angle2 + DIRECTION_GROUP_OFFSET)) / DIRECTION_GROUP_SIZE );
|
|
return step( abs(g1 - g2), EPSILON ) * step( abs(g1 - direction), EPSILON );
|
|
}
|
|
|
|
float2 IsSameDirection(float2 angles)
|
|
{
|
|
const float DIRECTION_GROUP_SIZE = 1.0f / 4.0f;
|
|
const float DIRECTION_GROUP_OFFSET = 1.0f / 16.0f;
|
|
float2 g = floor( frac(2.0 * (angles + DIRECTION_GROUP_OFFSET)) / DIRECTION_GROUP_SIZE );
|
|
return step( abs(g.x - g.y), EPSILON );
|
|
}
|
|
|
|
PS_OUT ps_edge_diff_canny_non_max_suppresion_and_diff( VS_OUT input )
|
|
{
|
|
DEFINE_CONSTANTS;
|
|
|
|
float4 img_00 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z, -ps_samp0Size.w ) ).xyzw;
|
|
float4 img_01 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0, -ps_samp0Size.w ) ).xyzw;
|
|
float4 img_02 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, -ps_samp0Size.w ) ).xyzw;
|
|
float4 img_10 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z, 0 ) ).xyzw;
|
|
float4 img_c = TEXTURE_READ_2D( samp, 0, input.uv0 ).xyzw;
|
|
float4 img_12 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, 0 ) ).xyzw;
|
|
float4 img_20 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z, ps_samp0Size.w ) ).xyzw;
|
|
float4 img_21 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0, ps_samp0Size.w ) ).xyzw;
|
|
float4 img_22 = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, ps_samp0Size.w ) ).xyzw;
|
|
|
|
//float4 maskDilated = TEXTURE_READ_2D( samp, 1, input.uv0 ).xyzw;
|
|
|
|
// Classify direction groups
|
|
float2 g_00 = IsDirection(img_c.zw, img_00.zw, 3.0f);
|
|
float2 g_01 = IsDirection(img_c.zw, img_01.zw, 2.0f);
|
|
float2 g_02 = IsDirection(img_c.zw, img_02.zw, 1.0f);
|
|
float2 g_10 = IsDirection(img_c.zw, img_10.zw, 0.0f);
|
|
float2 g_12 = IsDirection(img_c.zw, img_12.zw, 0.0f);
|
|
float2 g_20 = IsDirection(img_c.zw, img_20.zw, 1.0f);
|
|
float2 g_21 = IsDirection(img_c.zw, img_21.zw, 2.0f);
|
|
float2 g_22 = IsDirection(img_c.zw, img_22.zw, 3.0f);
|
|
|
|
// Compare gradient direction with that of its neighbors
|
|
float2 fIsEdge =
|
|
lerp( vec2_one, step( img_00.xy, img_c.xy ), g_00 ) *
|
|
lerp( vec2_one, step( img_01.xy, img_c.xy ), g_01 ) *
|
|
lerp( vec2_one, step( img_02.xy, img_c.xy ), g_02 ) *
|
|
lerp( vec2_one, step( img_10.xy, img_c.xy ), g_10 ) *
|
|
lerp( vec2_one, step( img_12.xy, img_c.xy ), g_12 ) *
|
|
lerp( vec2_one, step( img_20.xy, img_c.xy ), g_20 ) *
|
|
lerp( vec2_one, step( img_21.xy, img_c.xy ), g_21 ) *
|
|
lerp( vec2_one, step( img_22.xy, img_c.xy ), g_22 );
|
|
|
|
float2 fGradIntensity = fIsEdge * img_c.xy;
|
|
|
|
// Apply threshold
|
|
fGradIntensity = step( ps_reg0.x, fGradIntensity );
|
|
|
|
// Output edges that are in foreground but not in background
|
|
float fRes = saturate( fGradIntensity.x - fGradIntensity.y * IsSameDirection(img_c.zw) );
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( fRes, fRes, fRes, 1.0f );
|
|
return output;
|
|
}
|
|
|
|
// Short Edges Suppresion
|
|
|
|
PS_OUT ps_edge_diff_length(VS_OUT input)
|
|
{
|
|
float4 img_tl = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z, -ps_samp0Size.w ) ) * ps_reg0.x;
|
|
float4 img_t = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, -ps_samp0Size.w ) ) * ps_reg0.x;
|
|
float4 img_tr = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, -ps_samp0Size.w ) ) * ps_reg0.x;
|
|
float4 img_l = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z, 0.0 ) ) * ps_reg0.x;
|
|
float4 img_c = TEXTURE_READ_2D( samp, 0, input.uv0 ) * ps_reg0.x;
|
|
float4 img_r = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, 0.0 ) ) * ps_reg0.x;
|
|
float4 img_bl = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( -ps_samp0Size.z, ps_samp0Size.w ) ) * ps_reg0.x;
|
|
float4 img_b = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( 0.0, ps_samp0Size.w ) ) * ps_reg0.x;
|
|
float4 img_br = TEXTURE_READ_2D( samp, 0, input.uv0 + float2( ps_samp0Size.z, ps_samp0Size.w ) ) * ps_reg0.x;
|
|
|
|
float fConnectTl = (1.0f - saturate( img_t.x + img_l.x ));
|
|
float fConnectTr = (1.0f - saturate( img_t.x + img_r.x ));
|
|
float fConnectBl = (1.0f - saturate( img_b.x + img_l.x ));
|
|
float fConnectBr = (1.0f - saturate( img_b.x + img_r.x ));
|
|
|
|
float fToReceive = img_tl.y * fConnectTl;
|
|
fToReceive += img_tr.y * fConnectTr;
|
|
fToReceive += img_bl.y * fConnectBl;
|
|
fToReceive += img_br.y * fConnectBr;
|
|
fToReceive += img_t.y + img_l.y + img_r.y + img_b.y;
|
|
fToReceive *= saturate(img_c.x);
|
|
|
|
fToReceive -= img_c.w * ps_reg0.w; // Subtract what was given before and has come back
|
|
|
|
float fConnectionsAcc = img_c.x * ps_reg0.w + max(fToReceive, 0);
|
|
|
|
fToReceive -= ps_reg0.z; // Subtract 1 only at initialization
|
|
|
|
float fGiveConnections = saturate(img_t.x);
|
|
fGiveConnections += saturate(img_l.x);
|
|
fGiveConnections += saturate(img_r.x);
|
|
fGiveConnections += saturate(img_b.x);
|
|
fGiveConnections += saturate(img_tl.x) * fConnectTl;
|
|
fGiveConnections += saturate(img_tr.x) * fConnectTr;
|
|
fGiveConnections += saturate(img_bl.x) * fConnectBl;
|
|
fGiveConnections += saturate(img_br.x) * fConnectBr;
|
|
fGiveConnections *= saturate(img_c.x);
|
|
|
|
float fToGive = (fGiveConnections - 1.0f * ps_reg0.w) * fToReceive; // Do not keep connection that will not come back
|
|
|
|
float fToGivePrev = img_c.z * ps_reg0.w;
|
|
|
|
PS_OUT output;
|
|
output.clr = float4(fConnectionsAcc * ps_reg0.y, fToReceive * ps_reg0.y, fToGive * ps_reg0.y, fToGivePrev * ps_reg0.y);
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_edge_diff_length_suppresion(VS_OUT input)
|
|
{
|
|
float edge = TEXTURE_READ_2D( samp, 0, input.uv0 ).x * ps_reg0.x;
|
|
|
|
float fRes = step( ps_reg0.y, edge );
|
|
|
|
PS_OUT output;
|
|
output.clr = float4(fRes, fRes, fRes, 1.0f);
|
|
return output;
|
|
}
|
|
|
|
// Remove isolated pixels
|
|
|
|
PS_OUT ps_mask_remove_isolated_erode(VS_OUT input)
|
|
{
|
|
// Get info
|
|
GET_NEIGHBORHOOD_INFO;
|
|
|
|
// Check if one of the neighbors is background
|
|
float wantErode = 1.0f - Neighborhood_AllMask( 1, neighbors_x );
|
|
|
|
// Check if can erode
|
|
float canErode = isMask * wantErode;
|
|
|
|
// Output
|
|
float fMask = mask_c.x * (1.0f - canErode);
|
|
|
|
PS_OUT output;
|
|
output.clr = fMask;
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_remove_isolated_dilate(VS_OUT input)
|
|
{
|
|
// Get info
|
|
GET_NEIGHBORHOOD_INFO;
|
|
GET_NEIGHBORHOOD_INFO_EX;
|
|
|
|
float fPlayerIdx = Neighborhood_CommonPlayerIdx( mask_c.x, neighbors_x );
|
|
|
|
// Check if one of the neighbors is mask
|
|
float wantDilate = Neighborhood_AnyMask( mask_c.x, neighbors_x );
|
|
|
|
// Check if can dilate
|
|
float canDilate = (1.0f - isMask) * wantDilate;
|
|
|
|
// Output
|
|
float fMask = lerp( mask_c.x, fPlayerIdx, canDilate );
|
|
|
|
PS_OUT output;
|
|
output.clr = fMask;
|
|
return output;
|
|
}
|
|
|
|
// Body Part info
|
|
|
|
PS_OUT ps_mask_part_info_init(VS_OUT input)
|
|
{
|
|
float mask = TEXTURE_READ_2D( samp, 0, input.uv0 ).r; // Player Input
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( mask, 0.0f, 0.0f, 0.0f );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_part_info_mark(VS_OUT input)
|
|
{
|
|
DEFINE_CONSTANTS;
|
|
|
|
ITF_CONST float kDilationHead = DILATION_HEAD;
|
|
ITF_CONST float kDilationHands = DILATION_HANDS;
|
|
ITF_CONST float kDilationFeet = DILATION_FEET;
|
|
ITF_CONST float4 kDilationLimb = float4( kDilationHands.xx, kDilationFeet.xx );
|
|
ITF_CONST float4 sizeLimbs = ps_reg2.xyzw;
|
|
ITF_CONST float sizeHead = ps_reg3.z;
|
|
ITF_CONST float4 sizeFactorMarkLimbs = float4( ps_reg3.ww, ps_reg4.xx );
|
|
ITF_CONST float sizeFactorMarkHead = ps_reg4.yy;
|
|
|
|
// Get info
|
|
float mask = TEXTURE_READ_2D( samp, 0, input.uv0 ).r;
|
|
|
|
// Calculate distances
|
|
|
|
float4 fDirToLimbsX = float4( input.uv0.x - ps_reg0 );
|
|
float4 fDirToLimbsY = float4( input.uv0.y - ps_reg1 );
|
|
float4 fDistLimbs = sqrt(fDirToLimbsX*fDirToLimbsX + fDirToLimbsY*fDirToLimbsY) - sizeLimbs * sizeFactorMarkLimbs;
|
|
|
|
float fDistHead = length(input.uv0.xy - ps_reg3.xy) - sizeHead * sizeFactorMarkHead;
|
|
|
|
fDistLimbs = vec4_one - step( EPSILON, fDistLimbs );
|
|
fDistHead = 1.0f - step( EPSILON, fDistHead );
|
|
|
|
// Calculate dilations
|
|
float4 fDilationLimbs = kDilationLimb * fDistLimbs;
|
|
float fDilationHead = kDilationHead * fDistHead;
|
|
float fDilation = Max( fDilationHead, fDilationLimbs );
|
|
|
|
// Mark the size that the region needs to grow
|
|
float4 fSizeLimbs = sizeLimbs * fDistLimbs;
|
|
float fSizeHead = sizeHead * fDistHead;
|
|
float fSize = Max( fSizeHead, fSizeLimbs );
|
|
|
|
// Mark if region needs to keep holes
|
|
float fIgnoreHoles = step( EPSILON, fDistHead );
|
|
|
|
// Check if texel belongs to current player
|
|
float isPlayer = rectFunc( ps_reg4.z, ps_reg4.w, mask );
|
|
|
|
// Output
|
|
float3 outputValues = float3( fDilation * DILATION_NORM, fIgnoreHoles, fSize );
|
|
outputValues *= isPlayer;
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( 0.0f, outputValues );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_part_info_dilate(VS_OUT input)
|
|
{
|
|
// Get info
|
|
GET_NEIGHBORHOOD_INFO;
|
|
|
|
// Do not dilate if different players
|
|
float samePlayers = Neighborhood_SamePlayers( mask_c.x, neighbors_x );
|
|
|
|
// Dilation
|
|
float fDilation = Max( neighbors_y );
|
|
float wantDilate = ceil(fDilation);
|
|
|
|
// Ignore holes
|
|
float fIgnoreHoles = ITF_ANY4( neighbors_z );
|
|
|
|
// Size
|
|
float fSize = Max( neighbors_w );
|
|
fSize -= ps_samp0Size.z;
|
|
float maxSizeNotReached = step( 0, fSize );
|
|
|
|
// Check if can dilate
|
|
float noDilationInfo = 1.0f - ceil(mask_c.y);
|
|
float canDilate = (isMask * wantDilate * noDilationInfo * samePlayers * maxSizeNotReached);
|
|
|
|
// Output
|
|
float3 outputValues = float3( fDilation, fIgnoreHoles, fSize );
|
|
outputValues = lerp( mask_c.yzw, outputValues, canDilate );
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( mask_c.x, outputValues );
|
|
return output;
|
|
}
|
|
|
|
// Dilate Background
|
|
|
|
PS_OUT ps_mask_dilated_init(VS_OUT input)
|
|
{
|
|
float4 mask = TEXTURE_READ_2D( samp, 0, input.uv0 ).xyzw;
|
|
|
|
float fMaxDilation = ceil(mask.x) * max( mask.y, DILATION_NORM );
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( mask.x, fMaxDilation, mask.zx ); // Mask, MaxDilation, IgnoreHoles, Mask Original
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_dilated_dilate(VS_OUT input)
|
|
{
|
|
DEFINE_CONSTANTS;
|
|
|
|
// Get info
|
|
|
|
GET_NEIGHBORHOOD_INFO;
|
|
GET_NEIGHBORHOOD_INFO_EX;
|
|
|
|
// Do not dilate if different players
|
|
float samePlayers = Neighborhood_SamePlayers( mask_c.x, neighbors_x );
|
|
|
|
// Check if we should keep the existent holes to the minimum width
|
|
float fIgnoreHolesMarked = ITF_ANY4( neighbors_z );
|
|
|
|
float fIgnoreHoles = Neighborhood_SameRegions( neighbors_y, neighborsEx_y );
|
|
|
|
if ( fIgnoreHolesMarked < 0.5f )
|
|
{
|
|
float4 v1 = float4( neighbors_x.xz, neighborsEx_x.xz );
|
|
float4 v2 = float4( neighbors_x.yw, neighborsEx_x.yw );
|
|
v1 = vec4_one - min( v1, v2 );
|
|
float nonConnect = floor( v1.x * v1.y * v1.z * v1.w );
|
|
fIgnoreHoles = min( nonConnect, fIgnoreHoles );
|
|
}
|
|
|
|
// Dilate if possible
|
|
float fPlayerIdx = Max( mask_c.x, neighbors_x );
|
|
float wantDilate = ceil( Sum( neighbors_x ) / 4.0f );
|
|
float fRes = fPlayerIdx;
|
|
|
|
// Ensure maximum dilation for that pixel is not reached
|
|
float fMaxDilation = Max( neighbors_y );
|
|
float fMaxDilationNotReached = step( ps_reg0.x, fMaxDilation * DILATION_MAX - 0.5f );
|
|
|
|
// Check if can dilate
|
|
float canDilate = (1.0f - isMask) * wantDilate * fIgnoreHoles * samePlayers * fMaxDilationNotReached;
|
|
|
|
// Output
|
|
float3 outputValues = float3( fRes, fMaxDilation, fIgnoreHolesMarked );
|
|
outputValues = lerp( mask_c.xyz, outputValues, canDilate );
|
|
|
|
PS_OUT output;
|
|
output.clr = float4(outputValues, mask_c.w);
|
|
return output;
|
|
}
|
|
|
|
// Mask Shrink
|
|
|
|
PS_OUT ps_mask_refine_region_shrink_init(VS_OUT input)
|
|
{
|
|
float4 mask = TEXTURE_READ_2D( samp, 0, input.uv0 ).xyzw;
|
|
|
|
PS_OUT output;
|
|
output.clr = mask.xyxw; // Mask Dilated, MaxDilation, Mask Dilated, Mask Original
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_refine_region_shrink(VS_OUT input)
|
|
{
|
|
// Get info
|
|
|
|
GET_NEIGHBORHOOD_INFO;
|
|
|
|
float edge = TEXTURE_READ_2D( samp, 1, input.uv0 ).r;
|
|
float playerMask = ceil(mask_c.w);
|
|
|
|
// Check neigbhors
|
|
float fAllMask = Neighborhood_AllMask( 1, neighbors_x );
|
|
float fAnyMask = Neighborhood_AnyMask( 0, neighbors_x );
|
|
|
|
// Stop if foreground
|
|
float isBackground = 1.0f - max( edge, playerMask );
|
|
|
|
// Check if needs shrinking
|
|
float wantShrink = fAnyMask * (1.0f - fAllMask);
|
|
|
|
// Max Dilation
|
|
float fMaxShrinkNotReached = step( ps_reg0.x, mask_c.y * DILATION_MAX - 0.5f );
|
|
|
|
// Check if can shrink
|
|
float canShrink = isMask * wantShrink * isBackground * fMaxShrinkNotReached;
|
|
|
|
// Output
|
|
float fMask = mask_c.x * (1.0f - canShrink);
|
|
|
|
PS_OUT output;
|
|
output.clr = float4(fMask, mask_c.yzw);
|
|
return output;
|
|
}
|
|
|
|
// Fill color
|
|
|
|
PS_OUT ps_mask_fill_color_init(VS_OUT input)
|
|
{
|
|
float mask = TEXTURE_READ_2D( samp, 0, input.uv0 ).r;
|
|
float3 clr = TEXTURE_READ_2D( samp, 1, input.uv0 ).rgb;
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( mask, ceil(mask) * clr.rgb );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_fill_color_dilate(VS_OUT input)
|
|
{
|
|
DEFINE_CONSTANTS;
|
|
|
|
// Get info
|
|
|
|
GET_NEIGHBORHOOD_INFO;
|
|
|
|
float3 clr = TEXTURE_READ_2D( samp, 1, input.uv0 ).rgb;
|
|
float4 cma = TEXTURE_READ_2D( samp, 2, input.uv0 ).rgba;
|
|
|
|
// Check if dilating the pixel would connect two different players
|
|
float fPlayerIdx = Neighborhood_CommonPlayerIdx( mask_c.x, neighbors_x );
|
|
float fSamePlayers = ceil(fPlayerIdx);
|
|
|
|
// Check if one of the neighbors is mask and its color is continuous
|
|
|
|
float4 masks = ceil( neighbors_x );
|
|
|
|
float4 colorDistance = float4( colorDistance_avg( clr, mask_l.gba ),
|
|
colorDistance_avg( clr, mask_r.gba ),
|
|
colorDistance_avg( clr, mask_t.gba ),
|
|
colorDistance_avg( clr, mask_b.gba ) );
|
|
colorDistance += vec4_one - masks;
|
|
colorDistance += step( ps_reg0.yyyy, colorDistance );
|
|
|
|
float colorDistanceMin = Min( 0.95f, colorDistance );
|
|
|
|
float4 weights = step( colorDistance, colorDistanceMin );
|
|
float wantDilate = ITF_ANY4(weights);
|
|
|
|
float3 clrNeighbor = lerp( max( max( mask_l.gba * weights.x, mask_r.gba * weights.y ),
|
|
max( mask_t.gba * weights.z, mask_b.gba * weights.w ) ),
|
|
mask_c.gba,
|
|
isMask );
|
|
|
|
// Check if it's foreground, so that it can continue
|
|
float isForeground = step( ps_reg0.z, colorDistance_avg( clr, cma.rgb ) + cma.a );
|
|
|
|
// Check if can dilate
|
|
float canDilate = (1.0f - isMask) * fSamePlayers * wantDilate * isForeground;
|
|
|
|
// Output
|
|
float fMask = lerp( mask_c.x, fPlayerIdx, canDilate );
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( fMask, clrNeighbor );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_fill_color_combine(VS_OUT input)
|
|
{
|
|
float4 clr0 = TEXTURE_READ_2D( samp, 0, input.uv0 ).rgba; // Shrink
|
|
float4 clr1 = TEXTURE_READ_2D( samp, 1, input.uv0 ).rgba; // Fill color
|
|
float bg = ceil(TEXTURE_READ_2D( samp, 2, input.uv0 ).r);
|
|
|
|
PS_OUT output;
|
|
|
|
output.clr = float4( max(clr0.x, clr1.x * bg), clr0.yzw );
|
|
|
|
return output;
|
|
}
|
|
|
|
// Fill holes
|
|
|
|
PS_OUT ps_mask_fill_holes_init(VS_OUT input)
|
|
{
|
|
float4 mask = TEXTURE_READ_2D( samp, 0, input.uv0 ).xyzw;
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( mask.xyz, 0.0f ); // Mask Shrinked, MaxDilation Dilated, Mask Dilated, Dilation Count
|
|
return output;
|
|
|
|
}
|
|
|
|
PS_OUT ps_mask_fill_holes_dilate(VS_OUT input)
|
|
{
|
|
// Get info
|
|
GET_NEIGHBORHOOD_INFO;
|
|
#ifdef ITF_DURANGO
|
|
GET_NEIGHBORHOOD_INFO_EX;
|
|
#endif
|
|
|
|
// Check if dilating the pixel would connect two different players
|
|
float fPlayerIdx = Neighborhood_CommonPlayerIdx( mask_c.x, neighbors_x );
|
|
float fSamePlayers = ceil(fPlayerIdx);
|
|
|
|
// Check collision with background mask of other player
|
|
fSamePlayers *= Neighborhood_SamePlayers( mask_c.x, neighbors_z );
|
|
|
|
#ifdef ITF_DURANGO
|
|
// Check collision with other regions of same player
|
|
fSamePlayers *= Neighborhood_SameRegions( neighbors_y, neighborsEx_y );
|
|
#endif
|
|
|
|
// Check if one of the neighbors is mask
|
|
float wantDilate = Neighborhood_AnyMask( mask_c.x, neighbors_x );
|
|
|
|
// Check if can dilate
|
|
float canDilate = (1.0f - isMask) * fSamePlayers * wantDilate;
|
|
|
|
// Output
|
|
float2 outputValues = float2( fPlayerIdx, ps_reg0.x );
|
|
outputValues = lerp( mask_c.xw, outputValues, canDilate );
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( outputValues.x, mask_c.yz, outputValues.y );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_fill_holes_erode(VS_OUT input)
|
|
{
|
|
// Get info
|
|
GET_NEIGHBORHOOD_INFO;
|
|
|
|
// Check if one of the neighbors is background
|
|
float wantErode = 1.0f - Neighborhood_AllMask( 1, neighbors_x );
|
|
|
|
// Check if is in same dilate iteration
|
|
float fSameDilateIteration = step( ps_reg0.x, mask_c.w + ps_reg0.y );
|
|
|
|
// Check if can erode
|
|
float canErode = isMask * wantErode * fSameDilateIteration;
|
|
|
|
// Output
|
|
float fMask = mask_c.x * (1.0f - canErode);
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( fMask, mask_c.yzw );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_fill_holes_final(VS_OUT input)
|
|
{
|
|
// Get info
|
|
float4 mask_c = TEXTURE_READ_2D( samp, 0, input.uv0 ).xyzw;
|
|
|
|
// Output
|
|
float fMask = mask_c.x * ceil(mask_c.z);
|
|
|
|
PS_OUT output;
|
|
output.clr = float4(fMask, mask_c.yzw);
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_mask_final_erode(VS_OUT input)
|
|
{
|
|
// Get info
|
|
GET_NEIGHBORHOOD_INFO;
|
|
|
|
float originalMask = ceil( TEXTURE_READ_2D( samp, 1, input.uv0 ).w );
|
|
|
|
// Check if one of the neighbors is background
|
|
float wantErode = 1.0f - Neighborhood_AllMask( 1, neighbors_x );
|
|
|
|
// Ensure we don't go beyond the original mask
|
|
float keepOriginalMask = 1.0f - originalMask;
|
|
|
|
// Check if can erode
|
|
float canErode = isMask * wantErode * keepOriginalMask;
|
|
|
|
// Output
|
|
float fMask = mask_c.x * (1.0f - canErode);
|
|
|
|
PS_OUT output;
|
|
output.clr = float4( fMask, mask_c.yzw );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_temp(VS_OUT input)
|
|
{
|
|
float4 clr = TEXTURE_READ_2D( samp, 0, input.uv0 ).rgba;
|
|
|
|
PS_OUT output;
|
|
|
|
output.clr = ps_reg0 * lerp( clr.rgba, ceil(clr.rgba), ps_reg1 );
|
|
output.clr.rgb += output.clr.a;
|
|
output.clr.a = 1.0f;
|
|
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_plane_mask( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
float depth = TEXTURE_READ_2D( samp, 0, input.uv0 ).r;
|
|
float hasDepth = ceil(saturate(depth)); //0 no depth 1 depth
|
|
|
|
float3 rayOrig = NuiToWorld( float3(input.uv0, depth))/1000.0f;
|
|
float3 normal = normalize(ps_reg1.xyz);
|
|
float d = ps_reg1.w;
|
|
float t = clamp( dot( rayOrig, normal) + d - ps_reg0.z, 0.0f, 999.0f);
|
|
|
|
float finalValue = saturate(1.0f - saturate(ceil(t)) + ( 1.0f - hasDepth));
|
|
|
|
output.clr = float4( finalValue, finalValue, finalValue, finalValue);
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_blend_plane( VS_PLANE_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
|
|
float3 ndc = (input.pospostvs/input.pospostvs.w+1.0f)/2.0f;
|
|
float2 uvPlaneMask = float2(ndc.x, 1.0f - ndc.y);
|
|
|
|
//Animate
|
|
//ps_reg1 -> x,y :water speed z:"wave" speed w: time
|
|
float2 offsetWave = ps_reg1.z * float2( sin( ps_reg1.w + ndc.x*10.0f), sin( ps_reg1.w + ndc.y*10.0f));
|
|
float2 offsetLinear = ps_reg1.xy * ps_reg1.w;
|
|
float4 planeColor = TEXTURE_READ_2D(samp, 0, input.uv0 + offsetWave + offsetLinear);
|
|
|
|
float planeMaskAlpha = TEXTURE_READ_2D( samp, 1, uvPlaneMask ).x;
|
|
|
|
float planeTopPointScreen = lerp( ps_reg0.x, ps_reg0.y, ndc.x);
|
|
float alpha = planeColor.w * (1.0f - ndc.y/planeTopPointScreen) * planeMaskAlpha * ps_reg0.z;
|
|
|
|
output.clr = float4( planeColor.xyz, pow( alpha, 0.5f ));
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_lighten_blend( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
|
|
float4 colorA = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float4 colorB = TEXTURE_READ_2D( samp, 1, input.uv0 );
|
|
|
|
output.clr = lerp( colorA, float4(max(colorA.r, colorB.r), max(colorA.g, colorB.g), max(colorA.b, colorB.b), colorA.a ), pow(colorB.a, 0.5f));
|
|
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_screen_blend_inverse_alpha( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
|
|
const float3 vec3_one = float3(1.0f,1.0f,1.0f);
|
|
|
|
float4 colorA = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float4 colorB = TEXTURE_READ_2D( samp, 1, ((input.uv0 -0.5f) * ps_reg1.xy) + 0.5f + ps_reg1.zw );
|
|
|
|
float3 screenBlendColor = (vec3_one - ( vec3_one - colorA.rgb ) * ( vec3_one - colorB.rgb ));
|
|
output.clr = lerp( colorA, float4( lerp(screenBlendColor, colorA.rgb, ceil(colorB.a)), colorA.a), ps_reg0.x );
|
|
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_triple_layer_background ( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
|
|
ITF_CONST float factor = ps_reg0.x;
|
|
ITF_CONST float speedX = ps_reg0.y;
|
|
ITF_CONST float speedY = ps_reg0.z;
|
|
ITF_CONST float time = ps_reg0.w;
|
|
ITF_CONST float3 tintColor = ps_reg1.xyz;
|
|
|
|
// Sample sources
|
|
float3 firstLayerColor = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float3 secondLayerColor = TEXTURE_READ_2D( samp, 1, input.uv0 );
|
|
float3 thirdLayerColor = TEXTURE_READ_2D( samp, 2, input.uv0 + float2( speedX, speedY )*time );
|
|
float3 videoColor = TEXTURE_READ_2D( samp, 3, input.uv0 );
|
|
|
|
// Tint third layer color
|
|
float3 tintedLayeredColor = thirdLayerColor * tintColor;
|
|
|
|
// Compute final color from layers
|
|
float3 finalLayeredColor = lerp( firstLayerColor, tintedLayeredColor, 1.0f - secondLayerColor.r );
|
|
|
|
// Final color
|
|
float3 finalColor = lerp( videoColor, finalLayeredColor, factor );
|
|
|
|
output.clr = float4( finalColor, 1.0f );
|
|
|
|
return output;
|
|
}
|
|
|
|
//note: uniformly distributed, normalized rand, [0;1[
|
|
float nrand( float2 n )
|
|
{
|
|
return frac(sin(dot(n.xy, float2(12.9898, 78.233)))* 43758.5453);
|
|
}
|
|
|
|
PS_OUT ps_transition ( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
|
|
float3 oldImage = TEXTURE_READ_2D( samp, 0, input.uv0 );
|
|
float nrnd = nrand( input.uv0 + 0.07*ps_reg0.y );
|
|
|
|
output.clr = float4( ps_reg0.x*float3(nrnd,nrnd,nrnd) + (1. - ps_reg0.x)*oldImage, 1. );
|
|
return output;
|
|
}
|
|
|
|
PS_OUT ps_transition2 ( VS_OUT input )
|
|
{
|
|
PS_OUT output;
|
|
|
|
float progress = ps_reg0.x;
|
|
float time = ps_reg0.y;
|
|
float maxColorModificationRatio = ps_reg0.z;
|
|
float maxNoiseRatio = ps_reg0.w;
|
|
|
|
float timeOffset = frac((time+pow(1.f+frac(time),5.f))/10.f);
|
|
|
|
float offsetU = sin((input.uv0.y+timeOffset)*2.0f*PI)*0.05f;
|
|
offsetU += sin((input.uv0.y*10.f+frac(timeOffset))*2.f*PI)*0.05f;
|
|
offsetU += sin((input.uv0.y*5.f+frac(timeOffset*2.f))*2.f*PI)*0.05f;
|
|
offsetU *= progress;
|
|
|
|
float2 newUVCoord = input.uv0;
|
|
newUVCoord.x = fmod(input.uv0.x + offsetU, 1.f);
|
|
newUVCoord.y = fmod(newUVCoord.y + abs(sin(time/10.f))*sin(progress*3.f+time)*0.3f, 1.f);
|
|
float3 oldImage = TEXTURE_READ_2D( samp, 0, newUVCoord );
|
|
float colorCoef1 = abs(cos((newUVCoord.y+time)*4.f*PI));
|
|
float colorCoef2 = abs(cos((newUVCoord.y+time*7.f)*8.f*PI));
|
|
output.clr = float4(oldImage*(1.f-progress*maxColorModificationRatio) + progress*maxColorModificationRatio*float3(0.f,colorCoef1*colorCoef2*0.6f,1.f),1.f);
|
|
|
|
float nrnd = nrand( input.uv0 + 0.07*frac(time) );
|
|
output.clr = output.clr*(1.f-progress*maxNoiseRatio) + output.clr*progress*maxNoiseRatio*float4(nrnd,nrnd,nrnd,1.f);
|
|
|
|
return output;
|
|
}
|
|
|
|
#endif // PIXEL_PROFILE
|
|
|
|
#endif //AUTODANCE__FX
|