2019-01-29 08:15:40 +00:00
|
|
|
// -------------------------------------------------------------------------------- //
|
|
|
|
// Defines
|
|
|
|
#define MAX_DISTANCE 65536.0
|
|
|
|
#define NEAR_INFINITE 18446744073709551616.0
|
|
|
|
#define FLT_SMALL 0.001
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------- //
|
|
|
|
|
2018-11-08 12:52:43 +00:00
|
|
|
// OBS Default
|
|
|
|
uniform float4x4 ViewProj;
|
|
|
|
|
|
|
|
// Inputs
|
|
|
|
uniform texture2d _sdf;
|
|
|
|
uniform texture2d _image;
|
|
|
|
uniform float _inner_min;
|
|
|
|
uniform float _inner_max;
|
|
|
|
uniform float2 _inner_offset;
|
|
|
|
uniform float4 _inner_color;
|
|
|
|
uniform float _outer_min;
|
|
|
|
uniform float _outer_max;
|
|
|
|
uniform float2 _outer_offset;
|
|
|
|
uniform float4 _outer_color;
|
|
|
|
uniform float _threshold;
|
|
|
|
|
|
|
|
sampler_state sdfSampler {
|
2019-01-29 08:15:40 +00:00
|
|
|
Filter = Linear;
|
2018-11-08 12:52:43 +00:00
|
|
|
AddressU = Clamp;
|
|
|
|
AddressV = Clamp;
|
|
|
|
};
|
2019-01-29 08:15:40 +00:00
|
|
|
|
|
|
|
sampler_state sdfSampler1_1 {
|
|
|
|
Filter = Linear;
|
|
|
|
AddressU = Border;
|
|
|
|
AddressV = Border;
|
2019-01-31 01:25:09 +00:00
|
|
|
BorderColor = 000000FF;
|
2019-01-29 08:15:40 +00:00
|
|
|
};
|
|
|
|
|
2018-11-08 12:52:43 +00:00
|
|
|
sampler_state imageSampler {
|
2019-01-29 08:15:40 +00:00
|
|
|
Filter = Linear;
|
2018-11-08 12:52:43 +00:00
|
|
|
AddressU = Clamp;
|
|
|
|
AddressV = Clamp;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct VertDataIn {
|
|
|
|
float4 pos : POSITION;
|
|
|
|
float2 uv : TEXCOORD0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct VertDataOut {
|
|
|
|
float4 pos : POSITION;
|
|
|
|
float2 uv : TEXCOORD0;
|
|
|
|
};
|
|
|
|
|
|
|
|
VertDataOut VSDefault(VertDataIn v_in)
|
|
|
|
{
|
|
|
|
VertDataOut vert_out;
|
|
|
|
vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
|
|
|
|
vert_out.uv = v_in.uv;
|
|
|
|
return vert_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
float4 PS_SDFShadow_v1(VertDataOut v_in) : TARGET
|
|
|
|
{
|
|
|
|
float4 final = _image.Sample(imageSampler, v_in.uv);
|
2019-01-29 08:15:40 +00:00
|
|
|
|
2018-11-08 12:52:43 +00:00
|
|
|
if (_inner_max > 0 && final.a >= _threshold) {
|
|
|
|
float inner_dist = _sdf.Sample(sdfSampler, v_in.uv + _inner_offset).g;
|
|
|
|
float range = (_inner_max - _inner_min);
|
|
|
|
float str = clamp(inner_dist - _inner_min, 0, range) / range;
|
|
|
|
final = lerp(_inner_color, final, str);
|
|
|
|
}
|
|
|
|
if (_outer_max > 0 && final.a < _threshold) {
|
|
|
|
float outer_dist = _sdf.Sample(sdfSampler, v_in.uv + _outer_offset).r;
|
|
|
|
float range = (_outer_max - _outer_min);
|
|
|
|
float str = clamp(outer_dist - _outer_min, 0, range) / range;
|
|
|
|
final = lerp(_outer_color, float4(_outer_color.r, _outer_color.g, _outer_color.b, 0.0), str);
|
|
|
|
}
|
|
|
|
|
|
|
|
return final;
|
|
|
|
}
|
|
|
|
|
2019-01-29 08:15:40 +00:00
|
|
|
float4 PS_SDFShadow_v1_1(VertDataOut v_in) : TARGET
|
|
|
|
{
|
|
|
|
// V1.1:
|
|
|
|
// - No longer clipping off image using _threshold.
|
|
|
|
// - Inverse Gradient supported (max < min)
|
|
|
|
// - Negative Gradient support (min/max < 0)
|
|
|
|
|
|
|
|
// Support for inverse Gradient (Outer Shadow): Maximum < Minimum
|
|
|
|
//
|
|
|
|
// Min=4.00, Max=0.00:
|
|
|
|
// Expected: Max is fully visible, Min and higher is fully shadowed.
|
|
|
|
// d=0.5
|
|
|
|
// d = d - 4.00 (= -3.5)
|
|
|
|
// d = d / 4.00 (= -0.875, 87.5%)
|
|
|
|
// d is 87.5% visible
|
|
|
|
// Normal:
|
|
|
|
// Min=0.00, Max=4.00:
|
|
|
|
// d=0.5
|
|
|
|
// d = d - 0.00 (= 0.5)
|
|
|
|
// d = d / 4.00 (= 0.125, 12.5%)
|
|
|
|
// d is 12.5% visible
|
|
|
|
|
|
|
|
float4 final = float4(0., 0., 0., 0.);
|
|
|
|
float4 base = _image.Sample(imageSampler, v_in.uv);
|
|
|
|
|
|
|
|
//! Outer Shadow
|
|
|
|
// Are we allowed to draw an outer shadow?
|
2019-01-31 01:25:09 +00:00
|
|
|
float2 outer_sdf = _sdf.Sample(sdfSampler1_1, v_in.uv + _outer_offset).rg * float2(MAX_DISTANCE, MAX_DISTANCE);
|
2019-01-29 08:15:40 +00:00
|
|
|
if ((_outer_color.a > 0.) && (outer_sdf.r < MAX_DISTANCE)) {
|
|
|
|
// Calculate the true distance value:
|
|
|
|
// - If we are outside, this will be positive.
|
|
|
|
// - If we are inside, this will be negative.
|
|
|
|
float sdf_distance = outer_sdf.r - outer_sdf.g;
|
|
|
|
|
|
|
|
// Calculate the delta.
|
|
|
|
float delta = _outer_max - _outer_min;
|
|
|
|
float t1 = sdf_distance - _outer_min;
|
|
|
|
float t2 = clamp(t1 / delta, 0., 1.);
|
|
|
|
|
2019-01-30 02:37:46 +00:00
|
|
|
final = lerp(final, _outer_color, (1. - t2) * _outer_color.a);
|
2019-01-29 08:15:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Base Image
|
2019-01-30 02:37:46 +00:00
|
|
|
if (base.a > 0.) {
|
|
|
|
float3 rgb = base.rgb / base.a;
|
|
|
|
final = lerp(final, base, base.a);
|
|
|
|
}
|
2019-01-29 08:15:40 +00:00
|
|
|
|
|
|
|
//! Inner Shadow
|
|
|
|
// Are we allowed to draw an inner shadow?
|
2019-01-31 01:25:09 +00:00
|
|
|
float2 inner_sdf = _sdf.Sample(sdfSampler1_1, v_in.uv + _inner_offset).rg * float2(MAX_DISTANCE, MAX_DISTANCE);
|
2019-01-29 08:15:40 +00:00
|
|
|
if ((_inner_color.a > 0.) && (inner_sdf.g < MAX_DISTANCE) && (inner_sdf.r <= FLT_SMALL)) {
|
|
|
|
// Calculate the true distance value:
|
|
|
|
// - If we are outside, this will be positive.
|
|
|
|
// - If we are inside, this will be negative.
|
|
|
|
float sdf_distance = inner_sdf.g;
|
|
|
|
|
|
|
|
// Calculate the delta.
|
|
|
|
float delta = _inner_max - _inner_min;
|
|
|
|
float t1 = sdf_distance - _inner_min;
|
|
|
|
float t2 = clamp(t1 / delta, 0., 1.);
|
|
|
|
|
|
|
|
// Inner shadow does not affect alpha of image.
|
|
|
|
final.rgb = lerp(final.rgb, _inner_color.rgb, (1. - t2) * _inner_color.a);
|
|
|
|
}
|
|
|
|
|
|
|
|
return final;
|
|
|
|
}
|
|
|
|
|
2018-11-08 12:52:43 +00:00
|
|
|
technique Draw
|
|
|
|
{
|
|
|
|
pass
|
|
|
|
{
|
|
|
|
vertex_shader = VSDefault(v_in);
|
2019-01-29 08:15:40 +00:00
|
|
|
pixel_shader = PS_SDFShadow_v1_1(v_in);
|
2018-11-08 12:52:43 +00:00
|
|
|
}
|
|
|
|
}
|