如何在Shader中实现元素的「缩放无关性」?
解决矩形SDF边框随物体缩放变形的问题
当前问题核心是:物体缩放后,UV空间的XY轴比例改变,但SDF计算用的是未修正的等比例坐标,导致矩形形状随物体拉伸变形。只需将物体缩放参数应用到SDF坐标计算中,就能抵消缩放带来的拉伸效果。
修正思路
把SDF计算所用的坐标按物体XY缩放比例做归一化,让坐标空间始终保持等比例,无论物体如何缩放,矩形SDF的形状都能保持一致。
修改后的代码
矩形SDF函数(无需改动)
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); // 关键:用物体缩放反向修正坐标,抵消拉伸 position /= float2(objectScale.x, objectScale.y); // 生成宽度一致的边框,可自行调整borderWidth值 float borderWidth = 0.2; float sdf = rectangle(position, float2(3, 3)); float border = smoothstep(borderWidth, 0, sdf) - smoothstep(0, -borderWidth, sdf); float4 col = float4(border.xxx, 1); return col; }
说明
- 坐标修正:
position /= float2(objectScale.x, objectScale.y)这行代码让坐标按物体缩放比例反向缩放,确保SDF计算的坐标空间始终等比例,避免矩形随物体缩放变形。 - 边框实现:原代码用
step(0, sdf)得到的是填充矩形,改用两个smoothstep可计算出SDF在[-borderWidth, 0]区间的区域,生成宽度一致的边框,且不受物体缩放影响。 - 适配性:无论物体是(1,1)还是(1,0.125)这类缩放比例,修正后的坐标都会让矩形SDF保持原本形状,边框宽度也能稳定一致。
内容的提问来源于stack exchange,提问作者lafxyz
相关产品推荐
相关产品推荐

