Unity3d移动着色器透明度问题

时间:2018-06-06 15:08:41

标签: unity3d shader transparency alphablending depth-testing

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

Screenshot1

它应该看起来像这样:

Screenshot2

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
     }
    }
   }

1 个答案:

答案 0 :(得分:2)

  1. 着色器不亮因为您使用常规CG着色器而不是Surface着色器,其目的是方便地在场景后面提供照明。解决方案:从表面着色器模板开始新鲜
  2. Alpha混合未被利用,因为(col.a < _Cutoff) 始终为真或假,没有中间值,它始终完全显示或完全隐藏。最重要的是,您编写该条件的方式可能会在着色器中生成一些动态分支,请尝试静态分支而不是float newOpacity = (col.a < _Cutoff) ? 0.0 : 1.0;(在这种情况下,执行的代码始终相同,只有值更改通常更好用于perfs)。
  3. 着色器有 2次传递,这将阻止以后的批处理,这对于表演来说非常糟糕。一个是填充Zbuffer,另一个是进行alpha混合(2个操作不兼容)。 prepass无法正常工作,因为它使用原始网格填充缓冲区,而没有来自纹理的透明信息。当然你可以修改第一遍来做到这一点,但结果你看起来对于基本上只是一个非常直接的Surface着色器进行alpha测试
  4. 您可以阅读Unity公开的语义来控制Surface着色器中的alpha测试:https://docs.unity3d.com/Manual/SL-SurfaceShaders.html,特别是那部分:

      

    alphatest:VariableName - 启用Alpha剪切透明度。隔断   value是一个带VariableName的float变量。你也可能   想要使用 addshadow 指令来生成适当的阴影施法者   通过。

    或者,您可以将clip()方法与加入阴影结合使用,最有可能与clip(col.a - 0.5);

    一致