I tried to make border using rectangular sdf but with different scale it gets distorted.
I was thinking about object scale but can't figure how to do this myself
Object scales: (1, 1), (1, 0.125)
Desired result (Made in photoshop, slightly out of proportion)
There is vertex, fragment shader and rectangle function
float rectangle(float2 position, float2 size){
float2 component_wise_edge_distance = abs(position) - size;
float outside_distance = length(max(component_wise_edge_distance, 0));
float inside_distance = min(max(component_wise_edge_distance.x, component_wise_edge_distance.y), 0);
return outside_distance inside_distance;
}
v2f vert(appdata v){
v2f o;
o.position = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
float4 frag(v2f i) : SV_TARGET
{
half3x3 m = UNITY_MATRIX_M;
half3 objectScale = half3(
length( half3( m[0][0], m[1][0], m[2][0] ) ),
length( half3( m[0][1], m[1][1], m[2][1] ) ),
length( half3( m[0][2], m[1][2], m[2][2] ) )
);
float4 coords = i.uv;
coords *= 8;
float2 position = float2(coords.x - 4, coords.y - 4);
float sdf = step(0, rectangle(position, float2(3, 3)));
float4 col = float4(sdf.xxx, 1);
return col;
}
CodePudding user response:
Yes, you need to use the scale in your calculations.
First, center your coords so they run from -1 to 1 instead of 0 to 1.
float2 coords = i.uv * 2 - 1;
Scale your coords by your scale.
coords *= objectScale;
Now define your rectangle by scale - border.
float border = 0.2;
float2 size = float2(objectScale.x - border, objectScale.y - border);
float sdf = rectangle(coords, size);
sdf = step(0, sdf);
This will give you a fixed width border regardless of scale, though from your images it looks like you're expecting it to shrink with the scale. To do that, you could scale the border by the smallest axis.
border = border * min(objectScale.x, objectScale.y);
Note that using the object scale will not work with UI elements since by the time they get to your shader Unity has batched them all together and their object scale is meaningless. If that's the case you'll need to pass the scale in as a variable from a script.