141 lines
3.8 KiB
HLSL
141 lines
3.8 KiB
HLSL
|
|
#define CB_OUTLINEDMASK
|
|
|
|
#include "PlatformAdapter.fxh"
|
|
#include "ShaderParameters.fxh"
|
|
|
|
struct VS_VERTSCENE_OUTPUT
|
|
{
|
|
float4 Position : VS_OUT_POS;
|
|
float4 Color : COLOR0;
|
|
float2 UV : TEXCOORD0;
|
|
};
|
|
|
|
#ifdef VERTEX_PROFILE
|
|
|
|
struct VS_VERTSCENE_INPUT
|
|
{
|
|
float4 Position : POSITION;
|
|
float4 Color : COLOR0;
|
|
float2 Tex0 : TEXCOORD0;
|
|
};
|
|
VS_VERTSCENE_OUTPUT outlinedMask_vertex( VS_VERTSCENE_INPUT _In )
|
|
{
|
|
VS_VERTSCENE_OUTPUT output;
|
|
output.Position = mul(_In.Position, vs_mWorldViewProjection);
|
|
|
|
output.UV = _In.Tex0;
|
|
output.Color = _In.Color * vs_globalColor;
|
|
|
|
return output;
|
|
}
|
|
|
|
#endif // VERTEX_PROFILE
|
|
|
|
#ifdef PIXEL_PROFILE
|
|
|
|
REGISTER_SAMPLER(TextureSampler, 0) //g_diffuseTexture
|
|
|
|
float2 pickPoint(in float2 _center, in int _ID)
|
|
{
|
|
// constant picking kernel (it's a circle)
|
|
#ifdef DOUBLESAMPLE
|
|
const float2 kernel[32] = // this describes a circle, for optimal results
|
|
{
|
|
float2(1.0, 0.0),
|
|
float2(0.98078528, 0.195090322),
|
|
float2(0.923879533, 0.382683432),
|
|
float2(0.831469612, 0.555570233),
|
|
float2(0.707106781, 0.707106781),
|
|
float2(0.555570233, 0.831469612),
|
|
float2(0.382683432, 0.923879533),
|
|
float2(0.195090322, 0.98078528),
|
|
float2(0.0, 1.0),
|
|
float2(-0.195090322, 0.98078528),
|
|
float2(-0.382683432, 0.923879533),
|
|
float2(-0.555570233, 0.831469612),
|
|
float2(-0.707106781, 0.707106781),
|
|
float2(-0.831469612, 0.555570233),
|
|
float2(-0.923879533, 0.382683432),
|
|
float2(-0.98078528, 0.195090322),
|
|
float2(-1.0, 0.0),
|
|
float2(-0.98078528, -0.195090322),
|
|
float2(-0.923879533, -0.382683432),
|
|
float2(-0.831469612, -0.555570233),
|
|
float2(-0.707106781, -0.707106781),
|
|
float2(-0.555570233, -0.831469612),
|
|
float2(-0.382683432, -0.923879533),
|
|
float2(-0.195090322, -0.98078528),
|
|
float2(0.0, -1.0),
|
|
float2(0.195090322, -0.98078528),
|
|
float2(0.382683432, -0.923879533),
|
|
float2(0.555570233, -0.831469612),
|
|
float2(0.707106781, -0.707106781),
|
|
float2(0.831469612, -0.555570233),
|
|
float2(0.923879533, -0.382683432),
|
|
float2(0.98078528, -0.195090322)
|
|
};
|
|
#else
|
|
const float2 kernel[16] = // this describes a circle, for optimal results
|
|
{
|
|
float2(1.0, 0.0),
|
|
float2(0.923879, 0.382683),
|
|
float2(0.707106, 0.707106),
|
|
float2(0.382683, 0.923879),
|
|
float2(0.0, 1.0),
|
|
float2(-0.382682, 0.923879),
|
|
float2(-0.707106, 0.707106),
|
|
float2(-0.923879, 0.382683),
|
|
float2(-1.0, 0.0),
|
|
float2(-0.923879, -0.382683),
|
|
float2(-0.707106, -0.707106),
|
|
float2(-0.382683, -0.923879),
|
|
float2(0.0, -1.0),
|
|
float2(0.382683, -0.923879),
|
|
float2(0.707106, -0.707106),
|
|
float2(0.923879, -0.382683)
|
|
};
|
|
#endif
|
|
|
|
return (_center + float2(ps_om_params.x * kernel[_ID].x, ps_om_params.y * kernel[_ID].y));
|
|
}
|
|
|
|
float4 outlinedMask_pixel (VS_VERTSCENE_OUTPUT _In) : PS_OUT_COLOR
|
|
{
|
|
#ifdef DOUBLESAMPLE
|
|
const int nbSamples = 32;
|
|
#else
|
|
const int nbSamples = 16;
|
|
#endif
|
|
|
|
// sample at given UV (alpha only)
|
|
float vign = TEXTURE_READ_2D(TextureSampler, 0, _In.UV).a;
|
|
|
|
// if inside image, just otuput mask
|
|
float4 pixel;
|
|
if (vign >= 0.8f)
|
|
{
|
|
// avoid aliasing by interpolating beween mask and outline color
|
|
float t = saturate((1.0 - vign) * 5.0f); // [1.0 - 0.8] -> [0.0 - 1.0]
|
|
pixel = ps_om_maskColor * (1 - t) + ps_om_outlineColor * t;
|
|
}
|
|
// if outside, check if we are near the image, and outline if necessary
|
|
else
|
|
{
|
|
float around = 0.0f;
|
|
[unroll]
|
|
for (int i = 0; i < nbSamples; ++i)
|
|
{
|
|
// take only values that are in [0.8 - 1.0] i.e. considered as being part of the mask
|
|
around = max(TEXTURE_READ_2D(TextureSampler, 0, pickPoint(_In.UV, i)).a, around);
|
|
around *= step(0.8, around);
|
|
}
|
|
// also avoid aliasing by interpolating, again (but only the alpha here)
|
|
around = (around * 5.0) - 4.0; // [0.8 - 1.0] -> [0.0 - 1.0]
|
|
pixel = float4(ps_om_outlineColor.xyz, ps_om_outlineColor.a * around);
|
|
}
|
|
|
|
return pixel * _In.Color;
|
|
}
|
|
|
|
#endif // PIXEL_PROFILE
|