Unity | Shader基础知识(第十八集:Stencil应用-透视立方盒子)

目录

一、前言

二、场景布置

三、 shader部分

1.图片的部分

2.图片部分纯净代码

3.遮罩部分复习

4.深度写入 ZWrite

5.颜色遮罩ColorMask

6.遮罩纯净代码

四、场景中shader使用

五、作者的碎碎念


一、前言

因为这个内容稍微有点多,我尽力讲清楚了,如果不想看长篇大论的,可以直接下载成品。

上一集我们学了一个知识,叫做Stencil,这集我们把这部分知识扩展应用一下,做一个透视立方盒子。旋转到不同的面,展示不同的植物。这个植物可以是模型,也可以是图片。为了方便,我们用图片。(如图1所示)

图1 成品

二、场景布置

这个盒子是由6个quad的片组成的。把显示的面都放在里面,下方的quad加了草地的材质。(如图2所示)

图2 盒子墙

为了让盒子立体效果更好,在周围加了4个柱子,这四个柱子也只是cube拉长了。(如图3所示)

图3 柱子

因为我们展示了4个植物,所以也要放四个植物的图片,放在不同的方向,因为总要展示植物的正面。(如图4所示一个框一个植物)

图4 植物

最后也是最重要的,我们要沿着四周的墙建一圈遮罩(如图5所示),这个遮罩和墙大小一样,但注意墙的可见面是朝里的,但是遮罩的可见面是朝外的。因为你是从外面往里看,然后被遮住。

图5 遮罩

三、 shader部分

我们的shader分成两个,一个是挂在图片上的,一个是挂在遮罩上的。

1.图片的部分

根据之前学过的内容,图片部分就是之前美女图片的代码,链接如下。

Unity | Shader基础知识(第十七集:学习Stencil并做出透视效果)_unity stencil-CSDN博客

在这篇文章中,我们写了一个在遮罩后面才能看见的美女。不想回顾的,我把代码放在下面。

Shader "Custom/013-2"
{
Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
    }
    SubShader
    {
        Tags
        {
        "Queue" = "Transparent"
        }
        Stencil
		{
			Ref 1
			Comp Equal
			Pass Keep
		}
 
        Cull Off
 
        CGPROGRAM
        #pragma surface surf Lambert alpha:fade
 
        sampler2D _MainTex;
 
        struct Input
        {
            float2 uv_MainTex;
        };
 
        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c =tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

在上面的基础上,我们进行更改 。

需要更改的第一个部分,我们之前是在内部去设定测试模版的。(如图6所示)

图6 模版测试

但我们现在有4个树,每一个都在内部去改,我们就需要好多shader了,这样不方便,于是全部放到资源里。

    Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
        _SRef("Stencil Ref",Float) = 1
        _SComp("Stencil Comp",Float) = 8
        _SOp("Stencil Op",Float) = 2
    }

 然后在后面引用,只需要在原本的参数后面,书写中括号,再书写引用的符号,就可以了。

        Stencil
		{
            Ref[_SRef]
            Comp[_SComp]
            Pass[_SOp]
		}

这样我们就把参数改成外配的了!~


番外备注:

如果上一集你认真测试了,你会发现,总记不得等于到底是哪个,大于到底是哪个,如果有选项就好了,所以,unity为我们内置了选项,enum。

//选项    引用UnityEngine.Rendering.CompareFunction作为enum
[Enum(UnityEngine.Rendering.CompareFunction)] _SComp("Stencil Comp",Float) = 8
//选项    引用UnityEngine.Rendering.StencilOp作为enum
[Enum(UnityEngine.Rendering.StencilOp)] _SOp("Stencil Op",Float) = 2

这时候,你外面的材质球,对应的地方就会变成下拉选项。(如图7所示)

图7 下拉框

这样就方便多了!


因为我们的植物图片并不是一直显示,而是看见遮罩那一面的时候才显示,所以我们必须在遮罩后面渲染,因为遮罩打算放在Transparent层级,所以我们植物就比它晚一个点就行。

Tags
{
"Queue" = "Transparent+1"
}

到此为止,我们图片的所有更改都结束了。

2.图片部分纯净代码
Shader "Custom/014plant"
{
    Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
        _SRef("Stencil Ref",Float) = 1
        [Enum(UnityEngine.Rendering.CompareFunction)] _SComp("Stencil Comp",Float) = 8
        [Enum(UnityEngine.Rendering.StencilOp)] _SOp("Stencil Op",Float) = 2
    }
    SubShader
    {
        Tags
        {
        "Queue" = "Transparent+1"
        }
        Stencil
		{
            Ref[_SRef]
            Comp[_SComp]
            Pass[_SOp]
		}

        Cull Off

        CGPROGRAM
        #pragma surface surf Lambert alpha:fade

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c =tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
3.遮罩部分复习

也是之前学过的内容,遮罩部分也就是之前的遮罩代码,链接如下。

Unity | Shader基础知识(第十七集:学习Stencil并做出透视效果)_unity stencil-CSDN博客

不想回顾的,我把代码放在下面。

Shader "Custom/013-1"
{
Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
    }
    SubShader
    {
        Tags
        {
        "Queue" = "Transparent-1"
        }
        Stencil
		{
			Ref 1
			Comp Always
			Pass replace
		}
 
        Cull Off
 
        CGPROGRAM
        #pragma surface surf Lambert alpha:fade
 
        sampler2D _MainTex;
 
        struct Input
        {
            float2 uv_MainTex;
        };
 
        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c =tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

首先,我们依然把内置的模版测试改成外部可更改的,这部分略。之后我们需要学两个重要的知识点:深度写入和颜色遮罩。

4.深度写入 ZWrite

这个功能默认是开启的,也是一个非常好用的功能。

如果物体a被物体b挡住了,在大部分时候,我们是不需要去看物体a的,因为被挡住了,所以就看不见了。(如图8所示),方块的一部分,被平面挡住了。

图8 平面挡住方块

但是,你怎么知道方块在后面的?因为计算机检测了深度。如果此时把深度检测关了。计算机就觉得,大家都在第一面上,所以都显示。(如图9所示)

图9 关闭深度检测

我们进一步了解一下这个功能,在打开ZWrite时,如果它检测到物体是在前面的,并且,不是透明的(我设置不是透明,如图10所示)。计算机就会考虑,被一个不是透明的物体挡住了,那就不渲染了。所以这里不仅仅是看不见,而是它压根就不画了。

图10 

这里我们设置为普通物体(如图10所示),再打开深度写入,同时我们让前面的固体显示是透明的。就会出现(如图11所示)。后面的物体会以为自己挡住了,所以不画了,就会出现这个景象。

图11 以为自己被挡住

总结:

a.打开深度写入 ZWrite On

这时候,计算机会测试一下, 发现有谁是躲在后面的吗?干脆就不画这部分了

b.关闭了深度写入ZWrite Off

这时候,计算机不管你是否在后面,都会渲染。


5.颜色遮罩ColorMask

我们在unity里每次看图片,都有一个颜色通道功能。(如图12所示)

图12 颜色通道

在shader中,我们也自带了这个功能,我们可以选择只显示一个通道的内容。也可以选择都不显示。(就是前面我们深度写入中,虽然是物体,但做成了不显示的样子) 

标注了颜色遮罩,我们就可以选择只显示某一种或者某几种,或者不显示。

ColorMask RGBA        全部显示

ColorMask 0                全部关闭

ColorMask R                显示红色通道

ColorMask G                显示绿色通道 

ColorMask B                显示蓝色通道 

ColorMask A                显示透明通道 

ColorMask RG             显示红色和绿色通道

ColorMask RB             显示红色和蓝色通道

ColorMask RA             显示红色和透明通道

ColorMask GB             显示绿色和蓝色通道

ColorMask GA             显示绿色和透明通道

ColorMask BA             显示蓝色和透明通道

6.遮罩纯净代码

所以,我们的遮罩应该就是一个不显示的物体,要把颜色遮罩设置为0,但同时它不能挡住后面的花花草草,所以要把深度检测关了。

Shader "Custom/014"
{
    Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
        _SRef("Stencil Ref",Float) = 1
        [Enum(UnityEngine.Rendering.CompareFunction)] _SComp("Stencil Comp",Float) = 8
        [Enum(UnityEngine.Rendering.StencilOp)] _SOp("Stencil Op",Float) = 2
    }

    SubShader
    {
        Tags { "Queue" = "Geometry" }

        ZWrite off
        ColorMask 0
       
       Stencil
       {
        Ref[_SRef]
        Comp[_SComp]
        Pass[_SOp]
       }

        CGPROGRAM
       #pragma surface surf Lambert
       sampler2D _MainTex;

       struct Input
       {
       float2 uv_MainTex;
       };

       void surf(Input IN,inout SurfaceOutput o)
       {
       o.Albedo = tex2D (_MainTex, IN.uv_MainTex);
       
       }
        ENDCG
    }
    FallBack "Diffuse"
}

四、场景中shader使用

遮罩和图片的shader需要各自的材质并创建,这里我就略过了,直接进入参数配置。

我们的遮罩和植物图片应该是一一对应的。

对应植物1的遮罩:

植物1:

其他部分不变,其他植物使用不同的数就行,如3,4,5

这样就完成了所有的设置了。

五、作者的碎碎念

这集设置场景的部分比较多,但shader代码和之前差距不大哦。

猜你喜欢

转载自blog.csdn.net/weixin_49427945/article/details/140441663