在 Unity Shader 中,clamp 是一个常用的内置函数,用于将值限制在指定的范围内。

基本语法

clamp 函数有两种主要形式:

  1. 标量形式

    float clamp(float value, float min, float max);
    

    value 限制在 [min, max] 范围内。若 value < min,返回 min;若 value > max,返回 max;否则返回 value 本身。

  2. 向量形式

    float2 clamp(float2 value, float2 min, float2 max);
    float3 clamp(float3 value, float3 min, float3 max);
    // 其他向量类型(float4、half2 等)同理
    

    对向量的每个分量分别进行 clamping 操作。

常见应用场景

1. 限制纹理坐标

防止纹理坐标超出 [0, 1] 范围,避免采样错误:

float2 clampedUV = clamp(uv, 0.0, 1.0);  // 将 UV 限制在 [0,1] 内
fixed4 texColor = tex2D(_MainTex, clampedUV);

2. 颜色值归一化

确保颜色值在 [0, 1] 范围内,避免过亮或过暗:

fixed3 color = someCalculation();
color = clamp(color, 0.0, 1.0);  // 防止颜色溢出

3. 平滑过渡阈值

结合 smoothstep 实现渐变效果:

float t = someValue;
t = clamp(t, 0.0, 1.0);  // 确保 t 在 [0,1] 内,避免 smoothstep 异常
float smoothValue = smoothstep(0.2, 0.8, t);

4. 光照计算

限制点积结果为非负值,避免阴影区域出现负值:

float ndotl = dot(normal, lightDir);
ndotl = clamp(ndotl, 0.0, 1.0);  // 确保点积结果在 [0,1] 内

代码示例

以下是一个完整的 Shader 示例,展示 clamp 的用法:

Shader "Custom/ClampExample" {
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _ClampMin ("Clamp Min", Range(0, 1)) = 0.2
        _ClampMax ("Clamp Max", Range(0, 1)) = 0.8
    }
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float _ClampMin;
            float _ClampMax;

            v2f vert (appdata v) {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target {
                // 示例1:限制纹理坐标(防止超出边界)
                float2 clampedUV = clamp(i.uv, 0.0, 1.0);
                fixed4 texColor = tex2D(_MainTex, clampedUV);

                // 示例2:调整亮度并限制在 [_ClampMin, _ClampMax] 范围内
                fixed3 brightenedColor = texColor.rgb * 1.5;  // 增加亮度
                brightenedColor = clamp(brightenedColor, _ClampMin, _ClampMax;

                return fixed4(brightenedColor, texColor.a);
            }
            ENDCG
        }
    }
}

注意事项

  1. 性能clamp 是一个轻量级操作,但在复杂计算中频繁调用可能影响性能。
  2. 向量分量:对向量使用 clamp 时,确保 minmax 向量的每个分量都符合逻辑。
  3. 替代实现:若需要自定义 clamping 逻辑,可手动实现:
    float customClamp(float value, float min, float max) {
        return value < min ? min : (value > max ? max : value);
    }