float _BS_Remap(float v, float inMin, float inMax, float outMin, float outMax)
{
    return outMin + (v - inMin) * (outMax - outMin) / (inMax - inMin);
}

// CornerPart  : fraction of the mesh extent occupied by corners [0, 0.5]
//               Must match edge loop placement. e.g. 0.1 = loops at 0.4
// CornerScale : multiplier on the natural corner size.
//               1.0 = perfect proportion preservation at any scale
//               2.0 = corners twice as large, center shrinks
float NineSliceAxis(float p, float scale, float cornerPart, float cornerScale, float center)
{
    float pc = p - center;

    // Target corner size in object space
    // = natural world size (cornerPart * 1 at scale=1) * CornerScale / current scale
    float b = clamp(cornerPart * cornerScale / max(abs(scale), 0.0001), 0.0, 0.499);
    float cp = clamp(cornerPart, 0.0, 0.499);

    float result;
    if (pc < -0.5 + cp)
        result = _BS_Remap(pc, -0.5, -0.5 + cp, -0.5, -0.5 + b);
    else if (pc > 0.5 - cp)
        result = _BS_Remap(pc, 0.5 - cp, 0.5, 0.5 - b, 0.5);
    else
        result = _BS_Remap(pc, -0.5 + cp, 0.5 - cp, -0.5 + b, 0.5 - b);

    return result + center;
}

void BorderSlicer_float(float3 PositionOS, float3 Scale, float CornerPart, float CornerScale,
                                float3 Center, float3 Filter, out float3 Output)
{
    float3 sliced = float3(
        NineSliceAxis(PositionOS.x, Scale.x, CornerPart, CornerScale, Center.x),
        NineSliceAxis(PositionOS.y, Scale.y, CornerPart, CornerScale, Center.y),
        NineSliceAxis(PositionOS.z, Scale.z, CornerPart, CornerScale, Center.z)
    );

    Output = lerp(PositionOS, sliced, saturate(Filter));
}