Snaparazzi/Assets/MPUIKit/Runtime/Resources/Shaders/MPImageBasic.shader
2024-02-29 21:33:27 +01:00

411 lines
17 KiB
GLSL

Shader "MPUI/Basic Procedural Image"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" { }
_Color ("Tint", Color) = (1,1,1,1)
_StencilComp ("Stencil Comparison", Float) = 8
_Stencil ("Stencil ID", Float) = 0
_StencilOp ("Stencil Operation", Float) = 0
_StencilWriteMask ("Stencil Write Mask", Float) = 255
_StencilReadMask ("Stencil Read Mask", Float) = 255
_ColorMask ("Color Mask", Float) = 15
/* //SOFTMASK_HANDLE_START
[PerRendererData] _SoftMask ("Mask", 2D) = "white" {}
*/ //SOFTMASK_HANDLE_END
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
}
SubShader
{
Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" "CanUseSpriteAtlas" = "True" }
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask [_ColorMask]
Pass
{
Name "Default"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "UnityUI.cginc"
#include "2D_SDF.cginc"
/* //SOFTMASK_HANDLE_START
#include "Assets/SoftMask/Shaders/SoftMask.cginc" //SOFTMASK_INCLUDE_HANDLE
*/ //SOFTMASK_HANDLE_END
#pragma multi_compile_local _ UNITY_UI_CLIP_RECT
#pragma multi_compile_local _ UNITY_UI_ALPHACLIP
#pragma multi_compile_local _ CIRCLE TRIANGLE RECTANGLE NSTAR_POLYGON
#pragma multi_compile_local _ STROKE OUTLINED OUTLINED_STROKE
/* //SOFTMASK_HANDLE_START
#pragma multi_compile _ SOFTMASK_SIMPLE
*/ //SOFTMASK_HANDLE_END
struct appdata_t
{
float4 vertex: POSITION;
float4 color: COLOR;
float2 uv0: TEXCOORD0;
float2 uv1: TEXCOORD1;
float2 uv2: TEXCOORD2;
float2 uv3: TEXCOORD3;
float3 normal: NORMAL;
float4 tangent: TANGENT;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex: SV_POSITION;
fixed4 color: COLOR;
float2 uv0: TEXCOORD0;
float4 sizeData: TEXCOORD1;
float4 strokeOutlineCornerData: TEXCOORD2;
fixed4 outlineColor: COLOR1;
float4 shapeData: TEXCOORD3;
float4 worldPosition: TEXCOORD4;
/* //SOFTMASK_HANDLE_START
SOFTMASK_COORDS(5)
*/ //SOFTMASK_HANDLE_END
UNITY_VERTEX_OUTPUT_STEREO
};
sampler2D _MainTex;
fixed4 _Color;
fixed4 _TextureSampleAdd;
float4 _ClipRect;
float4 _MainTex_ST;
#if RECTANGLE
half rectangleScene(float4 _sizeData, float4 _shapeData, float _cornerStyle)
{
float2 _texcoord = _sizeData.xy;
float2 _size = float2(_sizeData.z, _sizeData.w);
float4 radius = _shapeData;
half4 c = half4(_texcoord, _size - _texcoord);
half rect = min(min(min(c.x, c.y), c.z), c.w);
bool4 cornerRects;
cornerRects.x = _texcoord.x < radius.x && _texcoord.y < radius.x;
cornerRects.y = _texcoord.x > _size.x - radius.y && _texcoord.y < radius.y;
cornerRects.z = _texcoord.x > _size.x - radius.z && _texcoord.y > _size.y - radius.z;
cornerRects.w = _texcoord.x < radius.w && _texcoord.y > _size.y - radius.w;
half cornerMask = any(cornerRects);
half4 cornerCircles;
cornerCircles.x = radius.x - length(_texcoord - radius.xx);//circle(_texcoord - radius.xx, radius.x);
cornerCircles.y = radius.y - length(_texcoord - half2(_size.x - radius.y, radius.y));//circle(_texcoord - half2(_size.x - radius.y, radius.y), radius.y);
cornerCircles.z = radius.z - length(_texcoord - (half2(_size.x, _size.y) - radius.zz));//circle(_texcoord - (half2(_size.x, _size.y) - radius.zz), radius.z);
cornerCircles.w = radius.w - length(_texcoord - half2(radius.w, _size.y - radius.w)); //circle(_texcoord - half2(radius.w, _size.y - radius.w), radius.w);
cornerCircles = min(max(cornerCircles, 0) * cornerRects, rect);
//cornerCircles = max(cornerCircles, 0) * cornerRects;
half corners = max(max(max(cornerCircles.x, cornerCircles.y), cornerCircles.z), cornerCircles.w);
corners = max(corners, 0.0) * cornerMask;
//return rect;
return rect*(cornerMask-1) - corners;
/*
half rect = rectanlge(_texcoord - half2(_size.x / 2.0, _size.y / 2.0), _size.x, _size.y);
half cornerCircle = circle(_texcoord - radius.xx, radius.x);
rect = _texcoord.x < radius.x && _texcoord.y < radius.x ? cornerCircle: rect;
cornerCircle = circle(_texcoord - half2(_size.x - radius.y, radius.y), radius.y);
rect = _texcoord.x > _size.x - radius.y && _texcoord.y < radius.y ? cornerCircle: rect;
cornerCircle = circle(_texcoord - (half2(_size.x, _size.y) - radius.zz), radius.z);
rect = _texcoord.x > _size.x - radius.z && _texcoord.y > _size.y - radius.z ? cornerCircle: rect;
cornerCircle = circle(_texcoord - half2(radius.w, _size.y - radius.w), radius.w);
rect = _texcoord.x < radius.w && _texcoord.y > _size.y - radius.w ? cornerCircle: rect;
*/
//max(max(max(cornerCircles.x, cornerCircles.y), cornerCircles.z), cornerCircles.w);
}
#endif
#if CIRCLE
float circleScene(float4 _sizeData, float4 _shapeData)
{
float2 _texcoord = _sizeData.xy;
float2 _size = _sizeData.zw;
float width = _size.x;
float height = _size.y;
float radius = lerp(_shapeData.x, min(width, height) / 2.0, _shapeData.y);
float sdf = circle(_texcoord - float2(width / 2.0, height / 2.0), radius);
return sdf;
}
#endif
#if TRIANGLE
half triangleScene(float4 _sizeData, float4 _shapeData)
{
float2 _texcoord = _sizeData.xy;
float2 _size = _sizeData.zw;
float width = _size.x;//_additionalData.z;
float height = _size.y;//_additionalData.w;
half sdf = sdTriangleIsosceles(_texcoord - half2(width / 2.0, height), half2(width / 2.0, -height));
//return sdf;
float3 _TriangleCornerRadius = max(_shapeData.xyz, float3(0.001, 0.001, 0.001));
// Left Corner
half halfWidth = width / 2.0;
half m = height / halfWidth;
half d = sqrt(1.0 + m * m);
half c = 0.0;
half k = -_TriangleCornerRadius.x * d + c;
half x = (_TriangleCornerRadius.x - k) / m;
half2 circlePivot = half2(x, _TriangleCornerRadius.x);
half cornerCircle = circle(_texcoord - circlePivot, _TriangleCornerRadius.x);
//sdf = sdfDifference(sdf, cornerCircle);
//return sdf;
x = (circlePivot.y + circlePivot.x / m - c) / (m + 1.0 / m);
half y = m * x + c;
half fy = map(_texcoord.x, x, circlePivot.x, y, circlePivot.y);
sdf = _texcoord.y < fy && _texcoord.x < circlePivot.x ? cornerCircle: sdf;
//return sdf;
// Right Corner
m = -m; c = 2.0 * height;
k = -_TriangleCornerRadius.y * d + c;
x = (_TriangleCornerRadius.y - k) / m;
circlePivot = half2(x, _TriangleCornerRadius.y);
cornerCircle = circle(_texcoord - circlePivot, _TriangleCornerRadius.y);
x = (circlePivot.y + circlePivot.x / m - c) / (m + 1.0 / m); y = m * x + c;
fy = map(_texcoord.x, circlePivot.x, x, circlePivot.y, y);
sdf = _texcoord.x > circlePivot.x && _texcoord.y < fy ? cornerCircle: sdf;
//Top Corner
k = -_TriangleCornerRadius.z * sqrt(1.0 + m * m) + c;
y = m * (width / 2.0) + k;
circlePivot = half2(halfWidth, y);
cornerCircle = circle(_texcoord - circlePivot, _TriangleCornerRadius.z);
x = (circlePivot.y + circlePivot.x / m - c) / (m + 1.0 / m); y = m * x + c;
fy = map(_texcoord.x, width - x, x, -1.0, 1.0);
fy = lerp(circlePivot.y, y, abs(fy));
sdf = _texcoord.y > fy ? cornerCircle: sdf;
return sdf;
}
#endif
#if NSTAR_POLYGON
half nStarPolygonScene(float4 _sizeData, float4 _shapeData)
{
float2 _texcoord = _sizeData.xy;
float width = _sizeData.z;
float height = _sizeData.w;
float size = height / 2 - _shapeData.y;
half str = sdNStarPolygon(_texcoord - half2(width / 2, height / 2), size, _shapeData.x, _shapeData.z) - _shapeData.y;
return str;
}
#endif
float2 rotateUV(float2 uv, float rotation, float2 mid)
{
return float2(
cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x,
cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y
);
}
float4 decode_0_1_16(float2 input){
float m = 65535.0;
float e = 256.0 / 255.0;
float n = 1.0 / m;
float4 c = float4(input.x, input.x, input.y, input.y);
c.yw *= m;
c = frac(c);
c -= float4(c.y, 0.0, c.w, 0.0) * n;
return clamp(c * e, 0.0, 1.0);
}
v2f vert(appdata_t v)
{
v2f OUT;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.vertex = UnityObjectToClipPos(v.vertex);
OUT.worldPosition = v.vertex;
OUT.color = v.color * _Color;
OUT.uv0 = v.uv0;
float2 size = v.uv1;
half strokeWidth = v.normal.y;
half falloff = v.normal.z;
float rotationData = v.uv3.x;
half cornerStyle = v.uv3.y;
half outlineWidth = v.normal.x;
half4 outlineColor = v.tangent;
float4 shapeData;
#if CIRCLE
shapeData.xy = v.uv2.xy;
#else
shapeData = decode_0_1_16(v.uv2) * min(size.x, size.y);
#endif
OUT.strokeOutlineCornerData = float4(strokeWidth, falloff, outlineWidth, cornerStyle);
OUT.outlineColor = outlineColor;
OUT.shapeData = shapeData;
// Rotation Values
half sign = rotationData > 0.0 ? 1 : -1;
float f = abs(rotationData);
float shapeRotation = frac(f) * 360.0 * sign;
// r.xyz -> constrainRotation, flipHorizontal, flipVertical
f = floor(f);
float p = f / 100.0;
float z = round(p);
p = frac(p) * 10.0;
float y = round(p);
p = frac(p) * 10.0;
float x = round(p);
half constrainRotation = x;
half flipHorizontal = y;
half flipVertical = z;
shapeRotation = radians(shapeRotation);
size = constrainRotation > 0.0 && frac(abs(shapeRotation) / 3.14159) > 0.1? float2(size.y, size.x) : size;
float2 shapeUv = constrainRotation > 0 ? v.uv0 : v.uv0 * size;
shapeUv = rotateUV(shapeUv, shapeRotation, constrainRotation > 0? float2(0.5, 0.5) : size * 0.5);
shapeUv*= constrainRotation > 0.0? size : 1.0;
shapeUv.x = lerp(shapeUv.x, abs(size.x - shapeUv.x), flipHorizontal);
shapeUv.y = lerp(shapeUv.y, abs(size.y - shapeUv.y), flipVertical);
OUT.sizeData = float4(shapeUv.x, shapeUv.y, size.x, size.y);
#ifdef UNITY_HALF_TEXEL_OFFSET
OUT.vertex.xy += (_ScreenParams.zw - 1.0) * float2(-1.0, 1.0);
#endif
/* //SOFTMASK_HANDLE_START
SOFTMASK_CALCULATE_COORDS(OUT, v.vertex);
*/ //SOFTMASK_HANDLE_END
return OUT;
}
fixed4 frag(v2f IN): SV_Target
{
half4 color = IN.color;
half2 texcoord = IN.uv0;
color = (tex2D(_MainTex, texcoord) + _TextureSampleAdd) * color;
float4 sizeData = IN.sizeData;
float strokeWidth = IN.strokeOutlineCornerData.x;
float falloff = IN.strokeOutlineCornerData.y;
float outlineWidth = IN.strokeOutlineCornerData.z;
half4 outlineColor = IN.outlineColor;
float cornerStyle = IN.strokeOutlineCornerData.w;
float4 shapeData = IN.shapeData;
half pixelScale = clamp(1.0/falloff, 1.0/2048.0, 2048.0);
float sdfData = 0;
#if RECTANGLE
sdfData = rectangleScene(sizeData, shapeData, cornerStyle);
#endif
#if CIRCLE
sdfData = circleScene(sizeData, shapeData);
#endif
#if TRIANGLE
sdfData = triangleScene(sizeData, shapeData);
#endif
#if NSTAR_POLYGON
sdfData = nStarPolygonScene(sizeData, shapeData);
#endif
#if !OUTLINED && !STROKE && !OUTLINED_STROKE
half shape = sampleSdf(sdfData, pixelScale);
color.a *= shape;
//color.a = sdfData;
#endif
#if STROKE
half shape = sampleSdfStrip(sdfData, strokeWidth, pixelScale);
color.a *= shape;
#endif
#if OUTLINED
float alpha = sampleSdf(sdfData, pixelScale);
float lerpFac = sampleSdf(sdfData + outlineWidth, pixelScale);
color = half4(lerp(outlineColor.rgb, color.rgb, lerpFac), lerp(outlineColor.a * color.a, color.a, lerpFac));
color.a *= alpha;
#endif
#if OUTLINED_STROKE
float alpha = sampleSdfStrip(sdfData, outlineWidth + strokeWidth, pixelScale);
float lerpFac = sampleSdfStrip(sdfData + outlineWidth, strokeWidth + falloff, pixelScale);
lerpFac = clamp(lerpFac, 0, 1);
color = half4(lerp(outlineColor.rgb, color.rgb, lerpFac), lerp(outlineColor.a * color.a, color.a, lerpFac));
color.a *= alpha;
#endif
/* //SOFTMASK_HANDLE_START
color.a *= SOFTMASK_GET_MASK(IN);
*/ //SOFTMASK_HANDLE_END
#ifdef UNITY_UI_CLIP_RECT
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
#endif
#ifdef UNITY_UI_ALPHACLIP
clip(color.a - 0.001);
#endif
return fixed4(color);
}
ENDCG
}
}
CustomEditor "MPUIKIT.Editor.MPImageShaderGUI"
}