ShaderLab学习小结(十六)泡泡

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ShaderLab学习小结(十六)泡泡相关的知识,希望对你有一定的参考价值。

一个球体,不论从哪去看,都是中心透明,向边上越来越不透,最后纯白,大概就像个泡泡一样
效果如下图:
技术分享图片
先看shader代码:

Shader "Custom/PaoPao" {
    //1.
    Properties{
        _MainColor("Main",color)=(1,1,1,1)
        _Scale("Scale",range(1,8))=1
    }
    SubShader {
        Tags{"queue"="Transparent"}   //2.
        pass{
            blend SrcAlpha OneMinusSrcAlpha    //3.
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "unitycg.cginc"
            #include "lighting.cginc"
            fixed4 _MainColor;
            float _Scale;
            struct v2f{
                float4 pos:POSITION;
                float3 normal:NORMAL;
                float3 wpos:TEXCOORD0;
            };
            v2f vert(appdata_base v)
            {
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
                o.normal=v.normal;
                o.wpos=mul(unity_ObjectToWorld,v.vertex).xyz;   //4.
                return o;
            }
            fixed4 frag(v2f IN):COLOR
            {
                float3 N = UnityObjectToWorldNormal(IN.normal);
                float3 V = normalize(UnityWorldSpaceViewDir(IN.wpos));    //5.
                float bright = pow(1-saturate(dot(N,V)),_Scale);      //6.
                fixed4 col=_MainColor;
                col.a*=bright;    //7.
                return col;
            }
            ENDCG
        }
    }
}

按照代码中的注释

1

定义一个主颜色和一个系数

    //1.
    Properties{
        _MainColor("Main",color)=(1,1,1,1)
        _Scale("Scale",range(1,8))=1
    }

2、3

很明显,物体是半透明的,所以

Tags{"queue"="Transparent"}   //2.
blend SrcAlpha OneMinusSrcAlpha    //3.

不用多解释

4

求个世界坐标

    o.wpos=mul(unity_ObjectToWorld,v.vertex).xyz;   //4.

5

计算世界空间中的视向量V

float3 V = normalize(UnityWorldSpaceViewDir(IN.wpos));    //5.

6、7

获取透明度alpha的系数,本例中是1乘这个系数,可以认为这个就是alpha

float bright = pow(1-saturate(dot(N,V)),_Scale);      //6.
col.a*=bright;    //7.

泡泡的形成主要就看这一句了
据我的理解(未必准确)
我们的视线是重直屏幕的,视向量方向垂直屏幕向外
再看球体
球体的法线方向是垂直球体表面向外的,那么不论我们从哪个角度去看一个球体,它中心的法线是垂直屏幕向外的
即和我们的视向量平行,且方向一至
根据向量点积的定义,两个向量点积等于两个向量长度相乘再乘上两个向量的夹角余弦
既然两个向量方向一样,夹角余弦得1,而两个向量都是单位向量,所以结果就是夹角余弦。
我们要让中心的透明度为0,所以就得1-saturate(dot(N,V)),然后pow函数求得0的_Scale次方还是0
最后乘以主颜色的alpha值,还是为0,最终得到的颜色是全透明的
同样,球体边缘的法向量平行于屏幕,也就是和视向量垂直,那么两个的点积得0,被1减得1
1的_Scale次方还是1,最后边缘的alpha值就是1,也就是不透明

这样就形成了这个泡泡,而且不论从什么方向看都一样

当然,如果想让这个泡泡接收平行光和环境光的影响,也可以
代码:

Shader "Custom/PaoPao" {
    Properties{
        _MainColor("Main",color)=(1,1,1,1)
        _Scale("Scale",range(1,8))=1
    }
    SubShader {
        Tags{"queue"="Transparent"}
        pass{
            tags{"lightmode"="forwardbase"}      //1.
            blend SrcAlpha OneMinusSrcAlpha
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "unitycg.cginc"
            #include "lighting.cginc"
            fixed4 _MainColor;
            float _Scale;
            struct v2f{
                float4 pos:POSITION;
                float3 normal:NORMAL;
                float3 wpos:TEXCOORD0;
            };
            v2f vert(appdata_base v)
            {
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
                o.normal=v.normal;
                o.wpos=mul(unity_ObjectToWorld,v.vertex).xyz;
                return o;
            }
            fixed4 frag(v2f IN):COLOR
            {
                float3 N = UnityObjectToWorldNormal(IN.normal);
                float3 V = normalize(UnityWorldSpaceViewDir(IN.wpos));
                float bright = pow(1-saturate(dot(N,V)),_Scale);
                fixed4 col=_MainColor;
                float3 L = normalize(UnityWorldSpaceLightDir(IN.wpos));//2.
                col*=_LightColor0*saturate(dot(N,L));    //3.
                col+=UNITY_LIGHTMODEL_AMBIENT; //4。
                col.a*=bright;   //5.
                return col;
            }
            ENDCG
        }
    }
}

1

光照模式forwardbase

2

世界坐标系光向量

3

平行光照

4

加上环境光

5

乘上alpha系数
效果如下图:
技术分享图片
我们转动平行光
技术分享图片
我们拖动材质的_Scale
技术分享图片
技术分享图片

以上是关于ShaderLab学习小结(十六)泡泡的主要内容,如果未能解决你的问题,请参考以下文章

ShaderLab学习小结接收平行光阴影

ShaderLab学习小结接收点光源阴影

ShaderLab学习小结(十八)cubemap

ShaderLab学习小结漫反射+高光+点光源

ShaderLab学习小结(十九)RenderToCubemap创建能反射周围环境的效果

ShaderLab学习小结在标准表面shader中加入顶点着色器函数