367 lines
13 KiB
Plaintext
367 lines
13 KiB
Plaintext
#include "/Engine/Private/GammaCorrectionCommon.ush"
|
|
|
|
#ifndef PI
|
|
#define PI 3.14159265359f
|
|
#endif
|
|
|
|
#ifndef INV_PI
|
|
#define INV_PI 0.31830988618379f
|
|
#endif
|
|
|
|
#ifndef HALF_PI
|
|
#define HALF_PI 1.57079632679f
|
|
#endif
|
|
|
|
#ifndef INV_255
|
|
#define INV_255 0.00392156862745f
|
|
#endif
|
|
|
|
#ifndef INV_360
|
|
#define INV_360 0.00277777777777f
|
|
#endif
|
|
|
|
half4 LGUI_UnpackUintColor(uint colorUint)
|
|
{
|
|
half4 ResultColor;
|
|
ResultColor.r = ((colorUint >> 24) & 0x000000ff) * INV_255;
|
|
ResultColor.g = ((colorUint >> 16) & 0x000000ff) * INV_255;
|
|
ResultColor.b = ((colorUint >> 8) & 0x000000ff) * INV_255;
|
|
ResultColor.a = ((colorUint >> 0) & 0x000000ff) * INV_255;
|
|
return ResultColor;
|
|
}
|
|
half4 LGUI_UnpackBytes(uint value)
|
|
{
|
|
half4 Result;
|
|
Result.x = (value >> 24) & 0x000000ff;
|
|
Result.y = (value >> 16) & 0x000000ff;
|
|
Result.z = (value >> 8) & 0x000000ff;
|
|
Result.w = (value >> 0) & 0x000000ff;
|
|
return Result;
|
|
}
|
|
|
|
int2 LGUI_UnpackCoordinate(float value)
|
|
{
|
|
uint PackedCoordinate = asuint(value);
|
|
int2 Coordinate;
|
|
Coordinate.x = (PackedCoordinate >> 16) & 0x0000ffff;
|
|
Coordinate.y = (PackedCoordinate >> 0) & 0x0000ffff;
|
|
return Coordinate;
|
|
}
|
|
float LGUI_ReadFloat(Texture2D DataTex, inout int3 Position)
|
|
{
|
|
float Result;
|
|
Result = DataTex.Load(Position).r;
|
|
Position.x += 1;
|
|
return Result;
|
|
}
|
|
float2 LGUI_ReadFloat2(Texture2D DataTex, inout int3 Position)
|
|
{
|
|
float2 Result;
|
|
Result.x = DataTex.Load(Position).r;
|
|
Position.x += 1;
|
|
Result.y = DataTex.Load(Position).r;
|
|
Position.x += 1;
|
|
return Result;
|
|
}
|
|
float4 LGUI_ReadFloat4(Texture2D DataTex, inout int3 Position)
|
|
{
|
|
float4 Result;
|
|
Result.x = DataTex.Load(Position).r;
|
|
Position.x += 1;
|
|
Result.y = DataTex.Load(Position).r;
|
|
Position.x += 1;
|
|
Result.z = DataTex.Load(Position).r;
|
|
Position.x += 1;
|
|
Result.w = DataTex.Load(Position).r;
|
|
Position.x += 1;
|
|
return Result;
|
|
}
|
|
half4 LGUI_ReadColor(Texture2D DataTex, inout int3 Position)
|
|
{
|
|
uint ColorUint = asuint(DataTex.Load(Position).r);
|
|
Position.x += 1;
|
|
half4 Color = LGUI_UnpackUintColor(ColorUint);
|
|
Color.rgb = sRGBToLinear(Color.rgb);
|
|
return Color;
|
|
}
|
|
|
|
// reference from https://www.shadertoy.com/view/4tGGRm
|
|
float sdRoundRect(float2 p, float2 b, float4 r)
|
|
{
|
|
r.xyzw = min(r.xyzw, min(b.x, b.y));
|
|
r.xy = (p.x > 0.0) ? r.xy : r.wz;
|
|
r.x = (p.y > 0.0) ? r.x : r.y;
|
|
float2 q = abs(p) - b + r.x;
|
|
float d = min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x;
|
|
// modified by me
|
|
d = d / fwidth(d);
|
|
d = saturate(0.5 - d);
|
|
return d;
|
|
}
|
|
float sdRoundRectInnerShadow(float2 p, float2 b, float4 r, float shadowSize)
|
|
{
|
|
r.xyzw = min(r.xyzw, min(b.x, b.y));
|
|
r.xy = (p.x > 0.0) ? r.xy : r.wz;
|
|
r.x = (p.y > 0.0) ? r.x : r.y;
|
|
float2 q = abs(p) - b + r.x;
|
|
float d = min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x;
|
|
|
|
d = saturate((0.0 - d) / shadowSize);
|
|
d = 1 - d;
|
|
d = smoothstep(0, 1, d);
|
|
return d;
|
|
}
|
|
float sdRoundRectOuterShadow(float2 p, float2 b, float4 r, float shadowSize)
|
|
{
|
|
r.xyzw = min(r.xyzw, min(b.x, b.y));
|
|
r.xy = (p.x > 0.0) ? r.xy : r.wz;
|
|
r.x = (p.y > 0.0) ? r.x : r.y;
|
|
float2 q = abs(p) - b + r.x;
|
|
float d = min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x;
|
|
|
|
d = saturate((0.0 - d) / shadowSize);
|
|
// d = 1 - d;
|
|
d = smoothstep(0, 1, d);
|
|
return d;
|
|
}
|
|
|
|
float RadialGradient(float2 uv, float2 quadSize, float2 center, float2 radius, float rotation)
|
|
{
|
|
float2 fragCoord = uv * quadSize;
|
|
rotation = radians(rotation);
|
|
float cosAngle = cos(rotation);
|
|
float sinAngle = sin(rotation);
|
|
float2x2 rotationMatrix = float2x2(cosAngle, sinAngle, -sinAngle, cosAngle);
|
|
fragCoord = mul(rotationMatrix, fragCoord - center) + center;
|
|
|
|
fragCoord.x = (fragCoord.x - center.x) * radius.y / radius.x + center.x;
|
|
float distToCenter = distance(fragCoord, center);
|
|
distToCenter /= radius.y;
|
|
distToCenter = saturate(distToCenter);
|
|
return distToCenter;
|
|
}
|
|
|
|
half4 BlendPremul(half4 bottom, half4 top)
|
|
{
|
|
half3 outColor;
|
|
half outA = top.a + bottom.a * (1.0f - top.a);
|
|
outColor = (top.rgb * top.a + bottom.rgb * bottom.a * (1.0f - top.a)) / outA;
|
|
if (outA == 0)
|
|
outColor.rgb = 0;
|
|
return half4(outColor, outA);
|
|
}
|
|
|
|
float LGUI_CalculateBuffer(Texture2D MainTex, SamplerState MainTexSampler, float2 UV0, float2 UV1, float2 UV2, float2 UV3, Texture2D DataTex, inout float3 Color, inout float Alpha)
|
|
{
|
|
half _TextureScaleMode;
|
|
float4 _CornerRadius;
|
|
float2 _QuadSize;
|
|
half _SoftEdge;
|
|
|
|
half _EnableBody;
|
|
half4 _BodyColor;
|
|
float2 _TextureUVCenter;
|
|
half _EnableGradient;
|
|
half4 _GradientColor;
|
|
float2 _GradientCenter;
|
|
float2 _GradientRadius;
|
|
float _GradientRotation;
|
|
|
|
half _EnableBorder;
|
|
float _BorderWidth;
|
|
half _EnableBorderGradient;
|
|
half4 _BorderColor;
|
|
half4 _BorderGradientColor;
|
|
float2 _BorderGradientCenter;
|
|
float2 _BorderGradientRadius;
|
|
float _BorderGradientRotation;
|
|
|
|
half _EnableInnerShadow;
|
|
half4 _InnerShadowColor;
|
|
float _InnerShadowSize;
|
|
float _InnerShadowBlur;
|
|
float2 _InnerShadowOffset;
|
|
|
|
half _OuterShadow;
|
|
half4 _OuterShadowColor;
|
|
float _OuterShadowSize;
|
|
float _OuterShadowBlur;
|
|
float2 _OuterShadowOffset;
|
|
|
|
half _EnableRadialFill;
|
|
float2 _RadialFillCenter;
|
|
float _RadialFillAngle;
|
|
float _RadialFillRotation;
|
|
|
|
//read data from texture
|
|
{
|
|
_OuterShadow = UV2.x;
|
|
int2 Coordinate = round(UV1);
|
|
int3 Position = int3(Coordinate, 0);
|
|
|
|
uint ByteUint = asuint(DataTex.Load(Position).r);
|
|
Position.x += 1;
|
|
uint BoolValues = (ByteUint >> 24) & 0x000000ff;
|
|
_TextureScaleMode = (ByteUint >> 16) & 0x000000ff;
|
|
|
|
_EnableBody = (BoolValues >> 7) & 1;
|
|
_SoftEdge = (BoolValues >> 6) & 1;
|
|
_EnableGradient = (BoolValues >> 5) & 1;
|
|
_EnableBorder = (BoolValues >> 4) & 1;
|
|
_EnableBorderGradient = (BoolValues >> 3) & 1;
|
|
_EnableInnerShadow = (BoolValues >> 2) & 1;
|
|
_EnableRadialFill = (BoolValues >> 1) & 1;
|
|
|
|
_QuadSize = LGUI_ReadFloat2(DataTex, Position);
|
|
|
|
_CornerRadius = LGUI_ReadFloat4(DataTex, Position);
|
|
_BodyColor = LGUI_ReadColor(DataTex, Position);
|
|
_TextureUVCenter = LGUI_ReadFloat2(DataTex, Position);
|
|
|
|
_GradientColor = LGUI_ReadColor(DataTex, Position);
|
|
_GradientCenter = LGUI_ReadFloat2(DataTex, Position);
|
|
_GradientRadius = LGUI_ReadFloat2(DataTex, Position);
|
|
_GradientRotation = LGUI_ReadFloat(DataTex, Position);
|
|
|
|
_BorderWidth = LGUI_ReadFloat(DataTex, Position);
|
|
_BorderColor = LGUI_ReadColor(DataTex, Position);
|
|
_BorderGradientColor = LGUI_ReadColor(DataTex, Position);
|
|
_BorderGradientCenter = LGUI_ReadFloat2(DataTex, Position);
|
|
_BorderGradientRadius = LGUI_ReadFloat2(DataTex, Position);
|
|
_BorderGradientRotation = LGUI_ReadFloat(DataTex, Position);
|
|
|
|
_InnerShadowColor = LGUI_ReadColor(DataTex, Position);
|
|
_InnerShadowSize = LGUI_ReadFloat(DataTex, Position);
|
|
_InnerShadowBlur = LGUI_ReadFloat(DataTex, Position);
|
|
_InnerShadowOffset = LGUI_ReadFloat2(DataTex, Position);
|
|
|
|
_RadialFillCenter = LGUI_ReadFloat2(DataTex, Position);
|
|
_RadialFillRotation = LGUI_ReadFloat(DataTex, Position);
|
|
_RadialFillAngle = LGUI_ReadFloat(DataTex, Position);
|
|
|
|
_OuterShadowColor = LGUI_ReadColor(DataTex, Position);
|
|
_OuterShadowSize = LGUI_ReadFloat(DataTex, Position);
|
|
_OuterShadowBlur = LGUI_ReadFloat(DataTex, Position);
|
|
_OuterShadowOffset = LGUI_ReadFloat2(DataTex, Position);
|
|
|
|
}
|
|
|
|
|
|
_GradientCenter.y = _QuadSize.y - _GradientCenter.y;
|
|
_BorderGradientCenter.y = _QuadSize.y - _BorderGradientCenter.y;
|
|
_InnerShadowOffset.y = -_InnerShadowOffset.y;
|
|
_OuterShadowOffset.y = -_OuterShadowOffset.y;
|
|
_RadialFillCenter.y = _QuadSize.y - _RadialFillCenter.y;
|
|
|
|
half4 outerShadowColor;
|
|
//outer shadow
|
|
{
|
|
float2 sdQuadSize = _QuadSize * 0.5f;
|
|
float2 quadSize = sdQuadSize + _OuterShadowSize + _OuterShadowBlur * 0.5f;
|
|
float2 sdFragCoord = (UV0 * 2.0f - float2(1.0f, 1.0f)) * (quadSize);
|
|
outerShadowColor = _OuterShadowColor;
|
|
float4 cornerRadius = _CornerRadius + _OuterShadowSize + _OuterShadowBlur;
|
|
float outerShadow = sdRoundRectOuterShadow(sdFragCoord, quadSize, cornerRadius, _OuterShadowBlur);
|
|
outerShadowColor.a *= outerShadow;
|
|
float dOuter = sdRoundRect(sdFragCoord + _OuterShadowOffset, sdQuadSize, _CornerRadius);
|
|
dOuter = 1.0f - dOuter;
|
|
half bodyVisible = sign(_EnableBody + _EnableBorder + _EnableInnerShadow); //is body visible?
|
|
outerShadowColor.a *= lerp(
|
|
dOuter // if body not visible, make it smooth
|
|
, sign(dOuter) //if body is visible, make it no smooth, because smooth can show a thin transparent line between body and outshadow
|
|
, bodyVisible);
|
|
|
|
UV0 = lerp(
|
|
UV0
|
|
, UV3 //use UV3 for RadialFill calculation
|
|
+ _OuterShadowOffset / _QuadSize //offset uv for RadialFill
|
|
, _OuterShadow);
|
|
}
|
|
|
|
half4 color;
|
|
//inner body
|
|
{
|
|
float2 sdQuadSize = _QuadSize * 0.5f;
|
|
float2 sdFragCoord = (UV0 * 2.0f - float2(1.0f, 1.0f)) * sdQuadSize;
|
|
|
|
float2 stretchUV = UV3;
|
|
float2 fitUV = UV3;
|
|
float2 envelopUV = UV3;
|
|
{
|
|
float fitUVX = (UV3.x - _TextureUVCenter.x) * _QuadSize.x / _QuadSize.y + _TextureUVCenter.x;
|
|
float fitUVY = (UV3.y - _TextureUVCenter.y) * _QuadSize.y / _QuadSize.x + _TextureUVCenter.y;
|
|
half lerpAlpha = saturate(sign(_QuadSize.x - _QuadSize.y));
|
|
fitUV = lerp(float2(UV3.x, fitUVY), float2(fitUVX, UV3.y), lerpAlpha);
|
|
envelopUV = lerp(float2(fitUVX, UV3.y), float2(UV3.x, fitUVY), lerpAlpha);
|
|
}
|
|
|
|
float2 texUV = lerp(lerp(stretchUV, fitUV, _TextureScaleMode), envelopUV, max(0, _TextureScaleMode - 1));
|
|
float4 MainTexColor = Texture2DSample(MainTex, MainTexSampler, texUV);
|
|
color = MainTexColor * _BodyColor;
|
|
|
|
half4 gradientColor;
|
|
{
|
|
float gradientLerpAlpha = RadialGradient(UV0, _QuadSize, _GradientCenter.xy, _GradientRadius.xy, _GradientRotation);
|
|
gradientColor = lerp(_GradientColor * MainTexColor, color, gradientLerpAlpha);
|
|
color = lerp(color, gradientColor, _EnableGradient);
|
|
}
|
|
|
|
color.a *= _EnableBody;
|
|
|
|
float dOuter = sdRoundRect(sdFragCoord, sdQuadSize, _CornerRadius);
|
|
float dInner = sdRoundRect(sdFragCoord, sdQuadSize - _BorderWidth, _CornerRadius - _BorderWidth);
|
|
half4 innerShadowColor;
|
|
{
|
|
float2 quadSize = sdQuadSize - _InnerShadowSize + _InnerShadowBlur * 0.5f;
|
|
float4 cornerRadius = _CornerRadius + _InnerShadowBlur * 0.5f - _InnerShadowSize;
|
|
cornerRadius = max(cornerRadius, _InnerShadowBlur);
|
|
float innerShadow = sdRoundRectInnerShadow(sdFragCoord - _InnerShadowOffset.xy, quadSize, cornerRadius, _InnerShadowBlur);
|
|
_InnerShadowColor.a *= innerShadow;
|
|
innerShadowColor = BlendPremul(color, _InnerShadowColor);
|
|
color = lerp(color, innerShadowColor, _EnableInnerShadow);
|
|
}
|
|
|
|
half4 borderColor;
|
|
{
|
|
borderColor = _BorderColor;
|
|
half4 borderGradientColor;
|
|
{
|
|
float borderGradientLerpAlpha = RadialGradient(UV0, _QuadSize, _BorderGradientCenter.xy, _BorderGradientRadius.xy, _BorderGradientRotation);
|
|
borderGradientColor = lerp(_BorderGradientColor, borderColor, borderGradientLerpAlpha);
|
|
borderColor = lerp(borderColor, borderGradientColor, _EnableBorderGradient);
|
|
}
|
|
borderColor.a *= (1.0f - dInner);
|
|
borderColor = BlendPremul(color, borderColor);
|
|
color = lerp(color, borderColor, _EnableBorder * sign(abs(_BorderWidth)));
|
|
}
|
|
color.a *= dOuter;
|
|
}
|
|
color = lerp(color, outerShadowColor, 1.0f * _OuterShadow);
|
|
|
|
float radialFillAlpha;
|
|
{
|
|
float2 fragCoord = UV0 * _QuadSize;
|
|
float2 centerToPixelDiff = fragCoord - _RadialFillCenter;
|
|
float2 centerToPixelVector = normalize(centerToPixelDiff);
|
|
|
|
float rotation = radians(_RadialFillRotation + _RadialFillAngle * 0.5f + 180.0f);
|
|
float cosAngle = cos(rotation);
|
|
float sinAngle = sin(rotation);
|
|
float2x2 rotationMatrix = float2x2(cosAngle, sinAngle, -sinAngle, cosAngle);
|
|
centerToPixelVector = mul(rotationMatrix, centerToPixelVector);
|
|
float angle = atan2(centerToPixelVector.y, centerToPixelVector.x);
|
|
float d = abs(angle * INV_PI);
|
|
d += _RadialFillAngle * INV_360 - 1.0f;
|
|
|
|
d /= fwidth(d);
|
|
d = saturate(d);
|
|
radialFillAlpha = color.a * d;
|
|
color.a = lerp(color.a, radialFillAlpha, _EnableRadialFill * sign(max(0, 360.0f - _RadialFillAngle)));
|
|
}
|
|
color.a *= sign(abs(_QuadSize.x)) * sign(abs(_QuadSize.y));//if size is 0
|
|
|
|
Color = color.rgb;
|
|
Alpha = color.a;
|
|
|
|
return 1;
|
|
} |