ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

「UnityShader笔记」10.透明度测试

2022-06-07 18:02:10  阅读:158  来源: 互联网

标签:10 MainTex Cutoff Color 透明度 笔记 fixed3 UnityShader worldNormal


Part1.概述

所谓透明度测试,就是根据一个不透明度的阈值,对需要进行透明度测试的物体进行筛选,通过筛选的片元将被正常渲染,否则会被直接剔除

透明度测试并没有真正实现半透明效果,它只是简单剔除了一些不透明度未到达阈值的片元

透明度测试是必须关闭深度写入的,因为如果一个片元被剔除,而仍然进行了深度写入,这会使得后来渲染的后方物体(如果有的话)仍然被遮挡,这是错误的

Part2.代码逐段分析

2.1属性快

    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Main Tex", 2D) = "white" {}
        _Cutoff("Alpha Cutoff", Range(0,1)) = 0.5
    }

在属性块,我们有额外的参数需要定义,即Cutoff参数,它定义了剔除透明片元的阈值,范围在0~1,凡是不透明度小于这个阈值的片元,在透明度测试中将被剔除

Tags{"Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout"}

在写Pass之前,我们需要设定几个重要tags,它们与透明度测试相关

Queue

这个tag设定了渲染顺序队列,Unity中默认的渲染队列如下:

将其设定为AlphaTest后,这使得其将会在不透明物体之后才被渲染,因为需要透明度测试的物体是关闭深度写入的,不能和不透明物体一起渲染

RenderType

常被用于着色器替换功能

IgnoreProjector

设置为true,代表不受投影器的影响

2.2顶点着色器

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

顶点着色器只做实现一些常规工作

2.3片元着色器

fixed4 frag(v2f i) : SV_Target{
    fixed3 worldNormal = normalize(i.worldNormal);
    fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));

    fixed4 texColor = tex2D(_MainTex, i.uv);

    clip(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);
}

片元着色器中,当我们对纹理采样完成后,需要根据采样的颜色结果进行透明度测试,内置的clip( )函数可以实现这个功能,当传入的参数<0时,片元将被剔除,因此我们将透明度减去阈值传入这个函数

Part3.效果图

Part4.完整代码

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'

Shader "Chapert8/alphaTest"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Main Tex", 2D) = "white" {}
        _Cutoff("Alpha Cutoff", Range(0,1)) = 0.5
    }
    SubShader
    {
        Tags{"Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout"}

        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.worldPos = mul(unity_ObjectToWorld, v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                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);

                clip(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 "Diffuse"
}

 

标签:10,MainTex,Cutoff,Color,透明度,笔记,fixed3,UnityShader,worldNormal
来源: https://www.cnblogs.com/MuTsuKi/p/16352809.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有