Skip to content

Instantly share code, notes, and snippets.

@all-iver
Created December 2, 2019 19:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save all-iver/59423ee929475d0792f5dcd004a05254 to your computer and use it in GitHub Desktop.
Save all-iver/59423ee929475d0792f5dcd004a05254 to your computer and use it in GitHub Desktop.
Custom round rectangle in Shapes2D
float4 _Roundness; // tl, tr, bl, br
fixed4 customRect(v2f i, float2 pos) {
float radius = min(_XScale, _YScale);
float distToCircle = radius - distance(float2(abs(pos.x), pos.y), float2(_XScale / 2 - radius, _YScale / 2));
float distToSide = _YScale / 2 - abs(pos.y);
float dist = when_ge(abs(pos.x), _XScale / 2 - radius) * min(distToSide, distToCircle)
+ when_le(abs(pos.x), _XScale / 2 - radius) * distToSide;
fixed4 color = color_from_distance(dist, fill(i.uv), _OutlineColor) * i.color;
if (_PreMultiplyAlpha == 1)
color.rgb *= color.a;
if (_UseClipRect == 1)
color.a *= UnityGet2DClipping(i.modelPos.xy, _ClipRect);
clip(color.a - 0.001);
return color;
}
fixed4 frag(v2f i) : SV_Target {
float2 pos = prepare(i.uv, i.modelPos.z);
if (_Roundness.x == 0 && _Roundness.y == 0 && _Roundness.z > 0 && _Roundness.w > 0)
return customRect(i, pos);
// get the roundness for this corner in world units, avoiding conditionals because
// they tend to break things on various platforms (gles3) and they are slow in
// shaders anyway
float tl = and(when_le(pos.x, 0), when_ge(pos.y, 0)) * _Roundness.x;
float tr = and(when_ge(pos.x, 0), when_ge(pos.y, 0)) * _Roundness.y;
float bl = and(when_le(pos.x, 0), when_le(pos.y, 0)) * _Roundness.z;
float br = and(when_ge(pos.x, 0), when_le(pos.y, 0)) * _Roundness.w;
float roundness = tl + tr + bl + br;
// radius of the circle at this corner, making sure not to go past halfway
float radius = min(min(_XScale / 2, roundness), _YScale / 2);
// handy distance to round rectangle formula
float2 extents = float2(_XScale, _YScale) / 2 - radius;
float2 delta = abs(pos) - extents;
// first component is distance to closest side when not in a corner circle, second
// is distance to the rounded part when in a corner circle
float dist = radius - (min(max(delta.x, delta.y), 0) + length(max(delta, 0)));
fixed4 color = color_from_distance(dist, fill(i.uv), _OutlineColor) * i.color;
if (_PreMultiplyAlpha == 1)
color.rgb *= color.a;
if (_UseClipRect == 1)
color.a *= UnityGet2DClipping(i.modelPos.xy, _ClipRect);
clip(color.a - 0.001);
return color;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment