288 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			288 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| // -------------------------------------------------------------------------------- //
 | |
| // Defines
 | |
| #define MAX_DISTANCE	65536.0
 | |
| #define NEAR_INFINITE	18446744073709551616.0
 | |
| #define FLT_SMALL		0.001
 | |
| #define PI				3.1415926535897932384626433832795
 | |
| #define HALFPI			1.5707963267948966192313216916398
 | |
| // -------------------------------------------------------------------------------- //
 | |
| 
 | |
| // -------------------------------------------------------------------------------- //
 | |
| // Samplers
 | |
| sampler_state imageSampler {
 | |
| 	Filter		= Linear;
 | |
| 	AddressU	= Clamp;
 | |
| 	AddressV	= Clamp;
 | |
| };
 | |
| 
 | |
| sampler_state sdfSampler {
 | |
| 	Filter		= Linear;
 | |
| 	AddressU	= Clamp;
 | |
| 	AddressV	= Clamp;
 | |
| 	BorderColor	= FFFFFFFF;
 | |
| };
 | |
| // -------------------------------------------------------------------------------- //
 | |
| 
 | |
| // -------------------------------------------------------------------------------- //
 | |
| // Global Parameters
 | |
| uniform float4x4 ViewProj;
 | |
| uniform texture2d pSDFTexture;
 | |
| uniform float pSDFThreshold;
 | |
| uniform texture2d pImageTexture;
 | |
| // -------------------------------------------------------------------------------- //
 | |
| 
 | |
| // -------------------------------------------------------------------------------- //
 | |
| // Shared Functions
 | |
| float4 PremultiplyTarget(float4 c, float4 t) {
 | |
| 	return lerp(float4(t.r, t.g, t.b, c.a), c, c.a);
 | |
| }
 | |
| 
 | |
| float LinearCurveFromValue(float v, float offset, float width,
 | |
| 						   float sharpness, float sharpnessInverse) {
 | |
| }
 | |
| 
 | |
| float GradientFromValue(float v, float offset, float width) {
 | |
| 	return ((v - offset) / width);
 | |
| }
 | |
| 
 | |
| // We can use any of the following gradient functions: https://www.desmos.com/calculator/bmbrncaiem
 | |
| float CurveEaseInOut(float v) {
 | |
| 	return cos((v-1)*PI)*0.5+0.5;
 | |
| }
 | |
| 
 | |
| float CurveEaseOut(float v) {
 | |
| 	return sin(v * HALFPI);
 | |
| }
 | |
| 
 | |
| float CurveEaseIn(float v) {
 | |
| 	return 1 - cos(v * HALFPI);
 | |
| }
 | |
| // -------------------------------------------------------------------------------- //
 | |
| 
 | |
| // -------------------------------------------------------------------------------- //
 | |
| // Default Vertex Shader
 | |
| 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;
 | |
| }
 | |
| // -------------------------------------------------------------------------------- //
 | |
| 
 | |
| // -------------------------------------------------------------------------------- //
 | |
| // Shadow Effects (Inner, Outer)
 | |
| uniform float4 pShadowColor;
 | |
| uniform float pShadowMin;
 | |
| uniform float pShadowMax;
 | |
| uniform float2 pShadowOffset;
 | |
| 
 | |
| float4 PSShadowOuter(VertDataOut v_in) : TARGET
 | |
| {
 | |
| 	float2 dist_ex = pSDFTexture.Sample(sdfSampler, v_in.uv + pShadowOffset).rg * MAX_DISTANCE;
 | |
| 	float dist = dist_ex.r - dist_ex.g;
 | |
| 	bool mask = (pImageTexture.Sample(imageSampler, v_in.uv).a <= pSDFThreshold);
 | |
| 
 | |
| 	if (!mask) {
 | |
| 		return float4(0.0, 0.0, 0.0, 0.0);
 | |
| 	}
 | |
| 
 | |
| 	float v = clamp((dist - pShadowMin) / (pShadowMax - pShadowMin), 0., 1.);
 | |
| 	return float4(pShadowColor.r, pShadowColor.g, pShadowColor.b, (1.0 - v) * pShadowColor.a);	
 | |
| }
 | |
| 
 | |
| technique ShadowOuter
 | |
| {
 | |
| 	pass
 | |
| 	{
 | |
| 		vertex_shader = VSDefault(v_in);
 | |
| 		pixel_shader  = PSShadowOuter(v_in);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| float4 PSShadowInner(VertDataOut v_in) : TARGET
 | |
| {
 | |
| 	float2 dist_ex = pSDFTexture.Sample(sdfSampler, v_in.uv + pShadowOffset).rg * MAX_DISTANCE;
 | |
| 	float dist = dist_ex.g - dist_ex.r;
 | |
| 	bool mask = (pImageTexture.Sample(imageSampler, v_in.uv).a > pSDFThreshold);
 | |
| 
 | |
| 	if (!mask) {
 | |
| 		return float4(0.0, 0.0, 0.0, 0.0);
 | |
| 	}
 | |
| 
 | |
| 	float v = clamp((dist - pShadowMin) / (pShadowMax - pShadowMin), 0., 1.);
 | |
| 	return float4(pShadowColor.r, pShadowColor.g, pShadowColor.b, (1.0 - v) * pShadowColor.a);	
 | |
| }
 | |
| 
 | |
| technique ShadowInner
 | |
| {
 | |
| 	pass
 | |
| 	{
 | |
| 		vertex_shader = VSDefault(v_in);
 | |
| 		pixel_shader  = PSShadowInner(v_in);
 | |
| 	}
 | |
| }
 | |
| // -------------------------------------------------------------------------------- //
 | |
| 
 | |
| // -------------------------------------------------------------------------------- //
 | |
| // Glow
 | |
| uniform float4 pGlowColor <
 | |
| 	string name = "Glow Color";
 | |
| 	string group = "Glow";
 | |
| >;
 | |
| uniform float pGlowWidth <
 | |
| 	string name = "Glow Width";
 | |
| 	string group = "Glow";
 | |
| 	float minimum = 0.01;
 | |
| 	float maximum = 16.0;
 | |
| 	float delta = 0.01;
 | |
| 	float default = 1.0;
 | |
| >;
 | |
| uniform float pGlowSharpness <
 | |
| 	string name = "Glow Sharpness";
 | |
| 	string group = "Glow";
 | |
| 	float minimum = 0.01;
 | |
| 	float maximum = 100.0;
 | |
| 	float delta = 0.01;
 | |
| 	float default = 1.0;
 | |
| 	string set_expr = "x / 100.0";
 | |
| >;
 | |
| uniform float pGlowSharpnessInverse <
 | |
| 	string name = "Glow Sharpness Inverse";
 | |
| 	string group = "Glow";
 | |
| 	string value_expr = "1.0 / (1.0 - pGlowSharpness)";
 | |
| 	bool visible = false;
 | |
| 	bool enabled = false;
 | |
| >;
 | |
| 
 | |
| float4 GlowShared(float dist) {
 | |
| 	
 | |
| 	// Calculate correct gradient value and also take into account glow alpha to not delete information.
 | |
| 	float v = clamp((GradientFromValue(dist, 0, pGlowWidth) - pGlowSharpness) * pGlowSharpnessInverse, 0.0, 1.0);
 | |
| 	return float4(pGlowColor.r, pGlowColor.g, pGlowColor.b, pGlowColor.a * (1.0 - v));
 | |
| }
 | |
| 
 | |
| float4 PSGlowOuter(VertDataOut v_in) : TARGET
 | |
| {
 | |
| 	float dist = pSDFTexture.Sample(sdfSampler, v_in.uv).r * MAX_DISTANCE;
 | |
| 	bool mask  = (pImageTexture.Sample(imageSampler, v_in.uv).a <= pSDFThreshold);
 | |
| 
 | |
| 	if (!mask) {
 | |
| 		return float4(0.0, 0.0, 0.0, 0.0);
 | |
| 	}
 | |
| 
 | |
| 	return GlowShared(dist);
 | |
| }
 | |
| 
 | |
| technique GlowOuter
 | |
| {
 | |
| 	pass
 | |
| 	{
 | |
| 		vertex_shader = VSDefault(v_in);
 | |
| 		pixel_shader = PSGlowOuter(v_in);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| float4 PSGlowInner(VertDataOut v_in) : TARGET
 | |
| {
 | |
| 	float dist = pSDFTexture.Sample(sdfSampler, v_in.uv).g * MAX_DISTANCE;
 | |
| 	bool mask  = (pImageTexture.Sample(imageSampler, v_in.uv).a > pSDFThreshold);
 | |
| 
 | |
| 	if (!mask) {
 | |
| 		return float4(0.0, 0.0, 0.0, 0.0);
 | |
| 	}
 | |
| 
 | |
| 	return GlowShared(dist);
 | |
| }
 | |
| 
 | |
| technique GlowInner
 | |
| {
 | |
| 	pass
 | |
| 	{
 | |
| 		vertex_shader = VSDefault(v_in);
 | |
| 		pixel_shader = PSGlowInner(v_in);
 | |
| 	}
 | |
| }
 | |
| // -------------------------------------------------------------------------------- //
 | |
| 
 | |
| // -------------------------------------------------------------------------------- //
 | |
| // Outline
 | |
| uniform float4 pOutlineColor <
 | |
| 	string name = "Outline Color";
 | |
| 	string group = "Outline";
 | |
| >;
 | |
| uniform float pOutlineWidth <
 | |
| 	string name = "Outline Width";
 | |
| 	string group = "Outline";
 | |
| 	float minimum = 0.01;
 | |
| 	float maximum = 16.0;
 | |
| 	float delta = 0.01;
 | |
| 	float default = 1.0;
 | |
| >;
 | |
| uniform float pOutlineOffset <
 | |
| 	string name = "Outline Offset";
 | |
| 	string group = "Outline";
 | |
| 	float minimum = -16.0;
 | |
| 	float maximum = 16.0;
 | |
| 	float delta = 0.01;
 | |
| 	float default = 0.0;
 | |
| >;
 | |
| uniform float pOutlineSharpness <
 | |
| 	string name = "Outline Sharpness";
 | |
| 	string group = "Outline";
 | |
| 	float minimum = 0.01;
 | |
| 	float maximum = 100.0;
 | |
| 	float delta = 0.01;
 | |
| 	float default = 1.0;
 | |
| 	string set_expr = "x / 100.0";
 | |
| >;
 | |
| uniform float pOutlineSharpnessInverse <
 | |
| 	string name = "Outline Sharpness Inverse";
 | |
| 	string group = "Outline";
 | |
| 	string value_expr = "1.0 / (1.0 - pOutlineSharpness)";
 | |
| 	bool visible = false;
 | |
| 	bool enabled = false;
 | |
| >;
 | |
| 
 | |
| float4 PSOutline(VertDataOut v_in) : TARGET
 | |
| {
 | |
| 	float2 iodist = pSDFTexture.Sample(sdfSampler, v_in.uv).rg * MAX_DISTANCE;
 | |
| 	float dist = iodist.r - iodist.g;
 | |
| 	
 | |
| 	// Calculate where we are in the outline.
 | |
| 	// We can use any of the following gradient functions: https://www.desmos.com/calculator/bmbrncaiem
 | |
| 	/// Base Curve
 | |
| 	float n = clamp(abs(dist - pOutlineOffset) / pOutlineWidth, 0.0, 1.0);
 | |
| 	/// Sharpness Curve
 | |
| 	float y1 = clamp((n - pOutlineSharpness) * pOutlineSharpnessInverse, 0.0, 1.0);
 | |
| 	float y2 = cos((y1 - 1) * PI) * 0.5 + 0.5;
 | |
| 	float y3 = sin(y1 * (PI / 2));
 | |
| 	float y4 = sin((y1 - 1) * (PI / 2)) + 1.0;
 | |
| 
 | |
| 	// Blend by Color.a so that our outline doesn't delete information.
 | |
| 	float l = 1.0 - ((1.0 - y1) * pOutlineColor.a);
 | |
| 
 | |
| 	return float4(pOutlineColor.r, pOutlineColor.g, pOutlineColor.b, pOutlineColor.a * (1.0 - y1));
 | |
| }
 | |
| 
 | |
| technique Outline
 | |
| {
 | |
| 	pass
 | |
| 	{
 | |
| 		vertex_shader = VSDefault(v_in);
 | |
| 		pixel_shader = PSOutline(v_in);
 | |
| 	}
 | |
| }
 | |
| // -------------------------------------------------------------------------------- //
 | |
| 
 |