在组合之前删除 tex2D 的一部分



>我编写一个统一的表面着色器来慢慢应用如下所示的锈蚀效果:

//Take 1 base color texture.
//Take 1 rust decal texture and 1 greyscale maps.
//Take 1 float range value.

然后:

//Use the range to remove from the grayscale map all the pixels that are darker than the value itself, then make theese greysclae map the rust alpha, then apply this composited rust layer over the color texture.

我设法做到了这一点:

        void surf (Input IN, inout SurfaceOutputStandard o) {
            half4 C = tex2D (_MainTex, IN.uv_MainTex); //Color Texture
            half4 R = tex2D (_RustTex, IN.uv_RustTex); //Rust texture
            half4 RG = tex2D (_RustGuide, IN.uv_RustGuide); //Greyscale texture
            //Here i need to compose the rust layer
            half4 RustResult = //??? Maybe a Clip() function or what? and how?
            //Here i apply the previusly composed layer over the color texture. Already tested and working.
            half4 Final = lerp (C, RustResult, RustResult.a);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }

那么我怎样才能完成这个着色器呢?我找不到有关表面着色器中可用函数的详细文档。

编辑:我几乎得到我需要的东西使用饱和();功能如下

    Properties {
    _MainTex ("Base (RGB)", 2D) = "" {} //the color texture
    _RustTex ("Rust Texture (RGB)", 2D) = "" {} //the rust texture
    _RustGuide ("Rust Guide (A)", 2D) = "" {} //the rust greyscale texture
    _RustAmount ("Rust Amount", range(0.0, 1.0)) = 0.0 //the rust amount float value
    _RustMultiplier ("Rust Multiplier", float) = 2
}
SubShader {
    Tags { "RenderType"="Opaque" }
    LOD 200
    CGPROGRAM
    #pragma target 3.0
    #include "UnityPBSLighting.cginc"
    #pragma surface surf Standard
    sampler2D _MainTex;
    sampler2D _RustTex;
    sampler2D _RustGuide;
    float _RustAmount;
    float _RustMultiplier;
    struct Input {
        float2 uv_MainTex;
        float2 uv_RustTex;
        float2 uv_RustGuide;
    };
    void surf (Input IN, inout SurfaceOutputStandard o) {
        half4 M = tex2D (_MainTex, IN.uv_MainTex);
        half4 R = tex2D (_RustTex, IN.uv_RustTex);
        half4 RG = tex2D (_RustGuide, IN.uv_RustGuide);
        half4 RustResult;
        RustResult.rgb = R.rgb;
        if (_RustAmount > 0) {
        RustResult.a = trunc(saturate(RG.a * _RustAmount * _RustMultiplier);
        }
        half4 Final = lerp (M, RustResult, RustResult.a);
        o.Albedo = Final.rgb;
        o.Alpha = Final.a;
    }
    ENDCG
} 
FallBack Off

}

这就是我需要的效果。现在唯一的问题是我如何模糊 alpha 的边缘?

使用该范围从灰度映射中删除所有像素 比值本身更暗

您不能简单地将值固定在浮点数以下_RustAmount吗?像这样:

float greyScaleMapValue = tex2D(_RustGuide, IN.uv_RustGuide).a; //assuming rust guide is stored as a single channel
float clampedMap = clamp(greyScaleMapValue , _RustAmount, 1); //clamped map stores a value clamped between _RustAmount and 1 -> every pixel darker than _RustAmount are 0
half3 albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
half3 rust = tex2D (_RustTex, IN.uv_RustTex).rgb;
float3 finalCol = lerp(albedo, rust, clampedMap); // all values in the map below _RustAmount will have plain albedo value, the other will be blended with rust using the map
return float4(finalCol,1);

请注意,上面的代码会产生一些从纹理到 rust 的突然过渡(更突然_RustmAmount大于零)。您希望最终重新映射[0,1]范围内钳位后大于零的每个值。

如果需要平滑过渡,可以将间隔[_RustAmount,1]重新映射到[0,1]

float clampedMapNormalized = (clampedMap - _RustAmount) / (1 - _RustAmount);

希望这有帮助

旁注:

  • 避免在着色器中分支(即使在制服上分支在现代硬件上不应该如此痛苦)
  • 如果贴图使用与其他 2 种纹理之一相同的 UV 坐标集(和平铺),则可以使用较少的纹理示例操作将其打包到相对 Alpha 通道中。
  • 由于您的着色器是不透明的,我想最终的 alpha 值无关紧要,所以我只是使用了一个float3来最小化要更改的值。

相关内容

  • 没有找到相关文章

最新更新