透明度测试 & 透明度混合

透明度测试

 1、透明测试是用于处理哪种透明需求

在游戏开发中对象的某些部位完全透明而其他部位完全不透明,这种透明需求往往不需要半透明效果,相对比较极端,只有看得见和看不见之分比如树叶、草、栅栏等等。(即一张图除了主要物体有颜色,其他区域都为透明)

2、透明测试的基本原理

基本原理:通过一个阈值来决定哪些像素应该被保留,哪些应该被丢弃

具体实现:片元携带的颜色信息中的透明度(A值),不满足条件时(通常是小于某个阈值),该片元就会被舍弃,被舍弃的片元不会在进行任何处理,不会对颜色缓冲区产生任何影响;满足条件时(通常是大于等于某个阈值),该片元会按照不透明物体的处理方式来处理

阈值判断使用的方法:利用CG中的内置函数:clip(参数)
该函数有重载,参数类型可以是 float4 float3 float2 float 等等,如果传入的参数任何一个分量是负数就会舍弃当前片元它的内部实现会用到一个 discard 指令,代表剔除该片元 不再参与渲染

void clip(float4 x) {
    if (any(x < 0))
        discard;
}

3、透明测试实现

  • 复制颜色纹理结合光照模型的Shader
  • 在属性中加一个阈值_Cutoff,取值范围为0~1,用来设定用来判断的阈值。并在CG中添加属性的映射成员
  • 将渲染队列设置为AlphaTest,并配合IgnoreProjector和RenderType一起设置
  • 在片元着色器中获取了颜色贴图颜色后,就进行阈值判断

注意:透明度测试不需要关闭深度写入

选用下面这张各个区域透明度不同的纹理图片

Shader "ShaderProj/3/TransparentTest"
{
    Properties
    {
        _MainTex("MainTex", 2D) = ""{}
        _MainColor("MainColor", Color) = (1,1,1,1)
        _SpecularColor("SpecularColor", Color) = (1,1,1,1)
        _SpecularNum("SpecularNum", Range(0,20)) = 15
        _CutOff("CutOff", Range(0,1)) = 0       // 透明度测试阈值
    }
    SubShader
    {
        Tags{
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="TransparentCutout"
            }

        Pass
        {
            Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _MainColor;
            fixed4 _SpecularColor;
            float _SpecularNum;
            fixed _CutOff;

            struct v2f
            {
                float4 pos:SV_POSITION;
                float2 uv:TEXCOORD0;
                float3 wNormal:NORMAL;
                float3 wPos:TEXCOORD01;
            };

            fixed3 getLambertColor(float3 normal, float3 lightDir, fixed3 albedo)
            {
                fixed3 color = _LightColor0 * albedo * max(0, dot(lightDir, normal));

                return color;
            }

            fixed3 getSpecularColor(float3 worldPos, float3 normal, float3 lightDir)
            {
                //float3 viewDir = normalize(_WorldSpaceCameraPos - worldPos);
                float3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
                float3 halfAngle = normalize(viewDir + lightDir);
                fixed3 color = _LightColor0 * _SpecularColor * pow(max(0, dot(normal, halfAngle)), _SpecularNum);

                return color;
            }
        
            v2f vert (appdata_base v)
            {
                v2f data;

                data.pos = UnityObjectToClipPos(v.vertex);
                data.wNormal = UnityObjectToWorldNormal(v.normal);
                data.wPos = mul(unity_ObjectToWorld, v.vertex);
                data.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                //data.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;

                return data;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // 透明度测试
                fixed4 texColor = tex2D(_MainTex, i.uv);
                clip(texColor.a - _CutOff);

                fixed3 albedo = texColor.rgb * _MainColor.rgb;                
                float3 lightDir = normalize(_WorldSpaceLightPos0);
                fixed3 lambertColor = getLambertColor(i.wNormal, lightDir, albedo);
                fixed3 specularColor = getSpecularColor(i.wPos, i.wNormal, lightDir);
                fixed3 color = lambertColor + specularColor + UNITY_LIGHTMODEL_AMBIENT.rgb * albedo;

                return fixed4(color, 1);
            }
            ENDCG
        }
    }
}

透明度混合

1、透明度混合是用来处理哪种需求

透明度测试,并不能用于实现半透明效果,它只存在看得见和完全看不见两种状态,一般用来处理镂空效果,透明度混合主要就是用来实现半透明效果的

2、透明度混合的基本原理

基本原理:关闭深度写入,开启混合,让片元颜色和颜色缓冲区中颜色进行混合计算

3、透明度混合实现

  • 我们复制 Lesson50 中颜色纹理结合光照模型的Shader(因为我们的测试资源没有法线贴图等数据)
  • 在属性中加一个阈值_AlphaScale
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值