#ifndef RM_COMMON #define RM_COMMON /// /// Constants /// #define RM_PI 3.14159265359 #define RM_DEGREES_TO_RADIANS (RM_PI / 180.0) #define RM_HALF_MIN 6.103515625e-5 // 2^-14, the same value for 10, 11 and 16-bit: https://www.khronos.org/opengl/wiki/Small_Float_Formats #define RM_MIN_CORNER_VALUE 1e-3 #define RM_MIN_CORNER_VALUE_RECT 1e-3 /// /// SDF methods. /// inline float RMPointVsRoundedBox(in float2 position, in float2 cornerCircleDistance, in float cornerCircleRadius) { return length(max(abs(position) - cornerCircleDistance, 0.0)) - cornerCircleRadius; } inline float FilterDistance(in float distance) { float pixelDistance = distance / fwidth(distance); #if defined(_INDEPENDENT_CORNERS) || defined(_UI_CLIP_RECT_ROUNDED_INDEPENDENT) // To avoid artifacts at discontinuities in the SDF distance increase the pixel width. return saturate(1.0 - pixelDistance); #else return saturate(0.5 - pixelDistance); #endif } inline float RMRoundCornersSmooth(in float2 position, in float2 cornerCircleDistance, in float cornerCircleRadius, in float smoothingValue) { float distance = RMPointVsRoundedBox(position, cornerCircleDistance, cornerCircleRadius); #if defined(_EDGE_SMOOTHING_AUTOMATIC) return FilterDistance(distance); #else return smoothstep(1.0, 0.0, distance / smoothingValue); #endif } inline float RMRoundCorners(in float2 position, in float2 cornerCircleDistance, in float cornerCircleRadius, in float smoothingValue) { #if defined(_TRANSPARENT) return RMRoundCornersSmooth(position, cornerCircleDistance, cornerCircleRadius, smoothingValue); #else return (RMPointVsRoundedBox(position, cornerCircleDistance, cornerCircleRadius) < 0.0); #endif } inline float RMFindCornerRadius(in float2 uv, in float4 radii) { if (uv.x < 0.5) { if (uv.y > 0.5) { return radii.x; } // Top left. else { return radii.z; } // Bottom left. } else { if (uv.y > 0.5) { return radii.y; } // Top right. else { return radii.w; } // Bottom right. } } /// /// UnityUI methods. /// inline float RMGet2DClippingRounded(in float2 position, in float4 clipRect, in float radius) { float2 halfSize = (clipRect.zw - clipRect.xy) * 0.5; float2 center = clipRect.xy + halfSize; float2 offset = position - center; return RMPointVsRoundedBox(offset, halfSize - radius, radius); } inline float RMGet2DClippingRoundedSoft(in float2 position, in float4 clipRect, in float radius) { return saturate(FilterDistance(RMGet2DClippingRounded(position, clipRect, radius))); } inline float RMGet2DClippingRoundedIndependent(in float2 position, in float4 clipRect, in float4 radii) { float2 halfSize = (clipRect.zw - clipRect.xy) * 0.5; float2 center = clipRect.xy + halfSize; float2 offset = position - center; float radius = RMFindCornerRadius(offset, radii); return RMPointVsRoundedBox(offset, halfSize - radius, radius); } inline float RMGet2DClippingRoundedIndependentSoft(in float2 position, in float4 clipRect, in float4 radii) { return saturate(FilterDistance(RMGet2DClippingRoundedIndependent(position, clipRect, radii))); } inline float RMUnityUIClipRect(in float2 position, in float4 clipRect, in float4 radii) { radii = max(radii, RM_MIN_CORNER_VALUE_RECT); #if defined(UNITY_UI_ALPHACLIP) return RMGet2DClippingRoundedIndependent(position, clipRect, radii) <= 0.0; #else return RMGet2DClippingRoundedIndependentSoft(position, clipRect, radii); #endif } #endif // RM_COMMON