目录

课时70:FragmentShader-Alpha和blend运算

课时71:FragmentShader-实现半透明1

课时72:FragmentShader-实现半透明2


课时70:FragmentShader-Alpha和blend运算

简单透明

Shader "Custom/NewSurfaceShader 30"
{
    SubShader
    {
        pass
        {
            blend srcalpha oneminussrcalpha
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "unitycg.cginc"
            struct v2f{
                float4 pos:POSITION;
            };
            v2f vert(appdata_base v){
                v2f o;
                o.pos=UnityObjectToClipPos(v.vertex);//屏幕坐标
                return o;
            }
            fixed4 frag(v2f IN) :COLOR
            {
                fixed4 color = fixed4(0,0,1,0.5);
                return color;
            }
            ENDCG
        }
    }
}

有问题

https://docs.unity3d.com/Manual/SL-CullAndDepth.html

Cull Back|Front|Off

ZWrite On|Off

ZTest

Offset

blend srcalpha oneminussrcalpha
zwrite off

颜色缓冲区,像素点颜色

Depth Buffer,深度缓冲区,和颜色缓冲区大小一样。

0-1

近裁剪面 0

远裁剪面 1

ztest,深度测试

LEqual ,是否比深度缓冲区的深度 小于等于,true:则颜色进入颜色缓冲区

zwrite :要不要把当前计算的深度值写入深度缓冲区,要通过深度测试。

通过深度,但是zwrite off,则只输出颜色,不改写深度缓冲区。

深度是有系统提供,根据摄像机和物体位置

unity shadergraph UI效果 unity shader frac_shader

课时71:FragmentShader-实现半透明1

半透明,zwrite off

unity shadergraph UI效果 unity shader frac_学习笔记_02

被物体遮挡则材质变成穿透+半透明的效果

半遮挡的情况

ztest greater:

pass
        {
            blend srcalpha oneminussrcalpha
            ztest greater
            zwrite on

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "unitycg.cginc"
            struct v2f{
                float4 pos:POSITION;
            };
            v2f vert(appdata_base v){
                v2f o;
                o.pos=UnityObjectToClipPos(v.vertex);//屏幕坐标
                return o;
            }
            fixed4 frag(v2f IN) :COLOR
            {
                fixed4 color = fixed4(0,0,1,0.5);
                return color;
            }
            ENDCG
        }

unity shadergraph UI效果 unity shader frac_#pragma_03

两个pass,一个greater,一个lequal

unity shadergraph UI效果 unity shader frac_shader_04

pass是按照顺序执行的,lequal要在前面,greater要在后面

Shader "Custom/NewSurfaceShader 31"
{
    SubShader
    {
        pass
        {
            blend srcalpha oneminussrcalpha
            ztest lequal
            zwrite on

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "unitycg.cginc"
            struct v2f{
                float4 pos:POSITION;
            };
            v2f vert(appdata_base v){
                v2f o;
                o.pos=UnityObjectToClipPos(v.vertex);//屏幕坐标
                return o;
            }
            fixed4 frag(v2f IN) :COLOR
            {
                fixed4 color = fixed4(0,0,1,0.5); 
                return color;
            }
            ENDCG
        }
        pass
        {
            blend srcalpha oneminussrcalpha
            ztest greater
            zwrite on

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "unitycg.cginc"
            struct v2f {
                float4 pos:POSITION;
            };
            v2f vert(appdata_base v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);//屏幕坐标
                return o;
            }
            fixed4 frag(v2f IN) :COLOR
            {
                fixed4 color = fixed4(1,0,0,1);
                return color;
            }
            ENDCG
        }
    }
}

unity shadergraph UI效果 unity shader frac_unity3d_05

教程没有提到这个顺序问题,

教程里面greater在前,lequal在后,或者在pass1里面,zwrite off,或者在pass2里面改成ztest less,或者pass2中的blend去掉。

在透明的墙后面,效果就不行了,因为透明墙的材质里面的zwrite off,这样ztest greater其实就没有效果了,不和透明的墙比较深度了。

unity shadergraph UI效果 unity shader frac_学习笔记_06

另外其实我的练习结果和教程有差异,摄像头的位置不同,看到的效果不一样。

课时72:FragmentShader-实现半透明2

没有深度写入的情况下,如何进行深度比较

深度贴图,Depth Texture

https://docs.unity3d.com/500/Documentation/Manual/SL-CameraDepthTexture.html

通过摄像机进行Shader置换

置换

没听懂....

虽然没有写入深度缓存

可以通过shader写入深度信息

Camera.SetReplacementShader

ResetReplacementShader

tags{"queue"="transparent","rendertype"="transparent"}

一个用来替换的,获取深度信息的shader

Shader "Custom/Depth"
{
    SubShader
    {
        tags{"rendertype"="transparent"}
        pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "unitycg.cginc"
            struct v2f{
                float4 pos:POSITION;
                float2 depth:TEXCOORD0;
            };
            v2f vert(appdata_base v){
                v2f o;
                o.pos=UnityObjectToClipPos(v.vertex);//屏幕坐标
                o.depth = o.pos.zw;
                return o;
            }
            fixed4 frag(v2f IN) :COLOR
            {
                float depth = Linear01Depth(IN.depth.x / IN.depth.y);
                fixed4 color = fixed4(depth,0,0,1);
                return color;
            }
            ENDCG
        }
    }
}

一个原来的透明shader,加上"rendertype"="transparent"

tags{"queue"="transparent" "rendertype"="transparent"}

一个替换的脚本

public class RepalcementShader : MonoBehaviour
{
    void Start()
    {
        Camera.main.SetReplacementShader(Shader.Find("Custom/Depth"), "rendertype");
    }
}

unity shadergraph UI效果 unity shader frac_学习笔记_07

结果只渲染了rendertype=transparent的物体

没有深度信息,就给它深度信息。

然后,没有了,不给出完整实现....就说一个思路。

最后给出个完整实现的效果图

unity shadergraph UI效果 unity shader frac_shader_08

Camera.main.SetReplacementShader(Shader.Find("Custom/Depth"), ""); 可以替换所有的材质,这个替换材质好像挺好用的,比如把所有材质替换成透明的。