You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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;
}

说明

  1. 坐标修正:position /= float2(objectScale.x, objectScale.y) 这行代码让坐标按物体缩放比例反向缩放,确保SDF计算的坐标空间始终等比例,避免矩形随物体缩放变形。
  2. 边框实现:原代码用step(0, sdf)得到的是填充矩形,改用两个smoothstep可计算出SDF在[-borderWidth, 0]区间的区域,生成宽度一致的边框,且不受物体缩放影响。
  3. 适配性:无论物体是(1,1)还是(1,0.125)这类缩放比例,修正后的坐标都会让矩形SDF保持原本形状,边框宽度也能稳定一致。

内容的提问来源于stack exchange,提问作者lafxyz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 17:21:06