目录
一、前言
二、场景布置
三、 shader部分
1.图片的部分
2.图片部分纯净代码
3.遮罩部分复习
4.深度写入 ZWrite
5.颜色遮罩ColorMask
6.遮罩纯净代码
四、场景中shader使用
五、作者的碎碎念
一、前言
因为这个内容稍微有点多,我尽力讲清楚了,如果不想看长篇大论的,可以直接下载成品。
上一集我们学了一个知识,叫做Stencil,这集我们把这部分知识扩展应用一下,做一个透视立方盒子。旋转到不同的面,展示不同的植物。这个植物可以是模型,也可以是图片。为了方便,我们用图片。(如图1所示)
二、场景布置
这个盒子是由6个quad的片组成的。把显示的面都放在里面,下方的quad加了草地的材质。(如图2所示)
为了让盒子立体效果更好,在周围加了4个柱子,这四个柱子也只是cube拉长了。(如图3所示)
因为我们展示了4个植物,所以也要放四个植物的图片,放在不同的方向,因为总要展示植物的正面。(如图4所示一个框一个植物)
最后也是最重要的,我们要沿着四周的墙建一圈遮罩(如图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所示)
但我们现在有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所示)
这样就方便多了!
因为我们的植物图片并不是一直显示,而是看见遮罩那一面的时候才显示,所以我们必须在遮罩后面渲染,因为遮罩打算放在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所示),方块的一部分,被平面挡住了。
但是,你怎么知道方块在后面的?因为计算机检测了深度。如果此时把深度检测关了。计算机就觉得,大家都在第一面上,所以都显示。(如图9所示)
我们进一步了解一下这个功能,在打开ZWrite时,如果它检测到物体是在前面的,并且,不是透明的(我设置不是透明,如图10所示)。计算机就会考虑,被一个不是透明的物体挡住了,那就不渲染了。所以这里不仅仅是看不见,而是它压根就不画了。
这里我们设置为普通物体(如图10所示),再打开深度写入,同时我们让前面的固体显示是透明的。就会出现(如图11所示)。后面的物体会以为自己挡住了,所以不画了,就会出现这个景象。
总结:
a.打开深度写入 ZWrite On
这时候,计算机会测试一下, 发现有谁是躲在后面的吗?干脆就不画这部分了。
b.关闭了深度写入ZWrite Off
这时候,计算机不管你是否在后面,都会渲染。
5.颜色遮罩ColorMask
我们在unity里每次看图片,都有一个颜色通道功能。(如图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代码和之前差距不大哦。