0

在 Unity3D(Unlit 版本)中使用自定义着色器时,我的 3D 对象与 alpha 重叠:

截图1

它应该看起来像这样:

截图2

Shader "Custom/Shader1" {
    Properties {
     _Color ("Main Color", Color) = (1,1,1,1)
     _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
     _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    }

    SubShader {
     Tags { "Queue"="Transparent" "RenderType"="Transparent" "IgnoreProjector"="True" }
     Pass {
         ZWrite On
         ColorMask 0
     }
     Pass {
      ZWrite Off // don't write to depth buffer 
      Blend SrcAlpha OneMinusSrcAlpha // use alpha blending
      CGPROGRAM

      #pragma vertex vert
      #pragma fragment frag

      uniform float4 _Color; // define shader property for shaders
      uniform sampler2D _MainTex;
      uniform float _Cutoff;

      struct vertexInput {
       float4 vertex : POSITION;
       float2 texcoord : TEXCOORD0;
      };
      struct vertexOutput {
       float4 pos : SV_POSITION;
       float2 tex : TEXCOORD0;
      };

      vertexOutput vert(vertexInput input) {
       vertexOutput output;

       output.tex = input.texcoord;
       output.pos = UnityObjectToClipPos(input.vertex);
       return output;
      }

      float4 frag(vertexOutput input) : COLOR {
       float4 col = tex2D(_MainTex, input.tex) * _Color;    
       float newOpacity = 1.0;
       if (col.a < _Cutoff) {
         newOpacity = 0.0;
       }
       return float4(col.r, col.g, col.b, newOpacity);
      }
      ENDCG
     }
    }
   }

我错过了什么吗?透明度 alpha 似乎与自身重叠。

编辑 1 我删除了第一遍,然后启用了 Zbuffer 并删除了if (col.a < _Cutoff)并根据其纹理让它成为动态的,但我仍然得到与第一张图像相同的结果。

Shader "Custom/Shader1" {
    Properties {
     _Color ("Main Color", Color) = (1,1,1,1)
     _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
     _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    }

    SubShader {
     Tags { "Queue"="Transparent" "RenderType"="Transparent" "IgnoreProjector"="True" }
     Pass {
      ZWrite On
      Blend SrcAlpha OneMinusSrcAlpha // use alpha blending
      CGPROGRAM

      #pragma vertex vert
      #pragma fragment frag

      uniform float4 _Color; // define shader property for shaders
      uniform sampler2D _MainTex;
      uniform float _Cutoff;

      struct vertexInput {
       float4 vertex : POSITION;
       float2 texcoord : TEXCOORD0;
      };
      struct vertexOutput {
       float4 pos : SV_POSITION;
       float2 tex : TEXCOORD0;
      };

      vertexOutput vert(vertexInput input) {
       vertexOutput output;

       output.tex = input.texcoord;
       output.pos = UnityObjectToClipPos(input.vertex);
       return output;
      }

      float4 frag(vertexOutput input) : COLOR {
       float4 col = tex2D(_MainTex, input.tex) * _Color;    
       return col;
      }
      ENDCG
     }
    }
   }
4

1 回答 1

2
  1. 着色器未点亮,因为您使用常规 CG 着色器而不是 Surface 着色器,其目的是方便地在场景后面提供照明。解决方案:从表面着色器模板重新开始
  2. Alpha 混合没有被利用,因为(col.a < _Cutoff) 它总是 true 或 false 没有中间值,它总是完全显示或完全隐藏。最重要的是,您编写该条件的方式可能会在着色器中生成一些动态分支,请尝试使用静态分支float newOpacity = (col.a < _Cutoff) ? 0.0 : 1.0;(在这种情况下,执行的代码始终相同,只有值发生变化,这通常对 perfs 更好)。
  3. 着色器有2 个通道,这将阻止以后进行批处理,这对性能非常不利。一个是填充 Zbuffer,另一个是进行 alpha 混合(2 个操作并不真正兼容)。prepass 不能正常工作,因为它用原始网格填充缓冲区,而没有来自纹理的透明度信息。当然你可以修改第一遍来做到这一点,但你寻找的结果本质上只是一个非常简单的表面着色器,带有 alpha 测试

您可以在此处阅读 Unity 公开的语义以控制 Surface 着色器中的 alpha 测试:https ://docs.unity3d.com/Manual/SL-SurfaceShaders.html ,特别是该部分:

alphatest:VariableName - 启用 alpha cutout 透明度。截止值位于带有 VariableName 的浮点变量中。您可能还想使用addshadow指令来生成正确的阴影投射通道。

或者,您可以将clip()方法与 addshadow结合使用,很可能沿着clip(col.a - 0.5);

于 2018-06-06T18:42:02.657 回答