(1)在Unity中新建一个场景。在本书资源中,该场景名为Scene_8_3。在Unity 5.2中,默认情况下场景将包含一个摄像机和一个平行光,并且使用了内置的天空盒子。在Window ->Lighting -> Skybox中去掉场景中的天空盒子。

command+N 新建场景

点击 window-rendering-lighting,点击 environment,点击 skybox material

(2)新建一个材质。在本书资源中,该材质名为AlphaTestMat。

(3)新建一个Unity Shader。在本书资源中,该Unity Shader名为Chapter8-AlphaTest。把新的Unity Shader赋给第2步中创建的材质。

(4)在场景中创建一个立方体,并把第2步中的材质赋给该模型。创建一个平面,使得平面位于立方体下面。

点击正方体中心和 shift,恢复默认视角。因为我弄乱了,调回来。

自己手动拉一下正方体到平面上方

(5)保存场景。
打开新建的Chapter8-AlphaTest,删除所有已有代码,并进行如下修改。
(1)首先,我们需要为这个Shader起一个名字:

(2)为了在材质面板中控制透明度测试时使用的阈值,我们在Properties语义块中声明一个范围在[0, 1]之间的属性_Cutoff:

_Cutoff参数用于决定我们调用clip进行透明度测试时使用的判断条件。它的范围是[0,1],这是因为纹理像素的透明度就是在此范围内。

(3)然后,我们在SubShader语义块中定义了一个Pass语义块:

(4)然后,我们使用CGPROGRAM和ENDCG来包围住CG代码片,来定义最重要的顶点着色器和片元着色器代码。首先,我们使用#pragma指令来告诉Unity,我们定义的顶点着色器和片元着色器叫什么名字。在本例中,它们的名字分别是vert和frag:

(5)为了使用Unity内置的一些变量,如_LightColor0,还需要包含进Unity的内置文件Lighting.cginc:

(6)为了和Properties语义块中声明的属性建立联系,我们需要定义和各个属性类型相匹配的变量:

(7)然后,我们定义了顶点着色器的输入和输出结构体,接着定义顶点着色器:

(8)最重要的透明度测试的代码在片元着色器中:

(9)最后,我们需要为这个Unity Shader设置合适的Fallback:

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/Chapter8-AlphaTest"
{
    Properties {
        _Color  ("Main  Tint",  Color)  =  (1,1,1,1)
        _MainTex  ("Main  Tex",  2D)  =  "white"  {}
        _Cutoff  ("Alpha  Cutoff",  Range(0,  1))  =  0.5 //_Cutoff参数用于决定我们调用clip进行透明度测试时使用的判断条件
    }

    Subshader {
        Tags {
            "Queue"="AlphaTest" 
            "IgnoreProjector"="True"  //IgnoreProjector设置为True,这意味着这个Shader不会受到投影器(Projectors)的影响。
            "RenderType"="TransparentCutout" //RenderType标签可以让Unity把这个Shader归入到提前定义的组(这里就是TransparentCutout组)中,以指明该Shader是一个使用了透明度测试的Shader
            //通常,使用了透明度测试的Shader都应该在SubShader中设置这三个标签
        }
        Pass {
            Tags  {  "LightMode"="ForwardBase" }
            CGPROGRAM
            #pragma  vertex  vert
            #pragma  fragment  frag
            #include  "Lighting.cginc"
            fixed4  _Color;
            sampler2D  _MainTex;
            float4  _MainTex_ST;
            fixed  _Cutoff;

            struct  a2v  {
                float4  vertex  :  POSITION;
                float3  normal  :  NORMAL;
                float4  texcoord  :  TEXCOORD0;
            };

            struct  v2f  {
                float4  pos  :  SV_POSITION;
                float3  worldNormal  :  TEXCOORD0;
                float3  worldPos  :  TEXCOORD1;
                float2  uv  :  TEXCOORD2;
            };

            v2f  vert(a2v  v)  {
                v2f  o;
                o.pos  =  UnityObjectToClipPos(v.vertex);
                o.worldNormal  =  UnityObjectToWorldNormal(v.normal);
                o.worldPos  =  mul(unity_ObjectToWorld,  v.vertex).xyz;
                o.uv  =  TRANSFORM_TEX(v.texcoord,  _MainTex);
                return  o;
            }

            fixed4  frag(v2f  i)  :  SV_Target  {
                fixed3  worldNormal  =  normalize(i.worldNormal);
                fixed3  worldLightDir  =  normalize(UnityWorldSpaceLightDir(i.worldPos));
                fixed4  texColor  =  tex2D(_MainTex,  i.uv);

                //  Alpha  test
                clip  (texColor.a  -  _Cutoff);//判断它的参数,即texColor.a - _Cutoff是否为负数,如果是就会舍弃该片元的输出
                fixed3  albedo  =  texColor.rgb  *  _Color.rgb;
                fixed3  ambient  =  UNITY_LIGHTMODEL_AMBIENT.xyz  *  albedo;
                fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));
                return  fixed4(ambient  +  diffuse,  1.0);
            }
            ENDCG
        }
    }

    Fallback  "Transparent/Cutout/VertexLit"
}

https://github.com/candycat1992/Unity_Shaders_Book/blob/master/Assets/Textures/Chapter8/transparent_texture.psd

下载transparent_texture.psd,拖到 Assets 里

把 texture 给对应的 mat

调整 Alpha Cutoff

0.5

1

0

0.738

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐