【猫猫的Unity Shader之旅】之玻璃材质

今天我们用学过的Shader知识实现一个简单的玻璃材质。

首先,玻璃是半透明的

玻璃最主要的特点就是它是透明的,不同的玻璃有不同的不透明度,水杯的透明度比较低,而装药品的棕色玻璃瓶不透明度就比较高。当然,玻璃也有一定的颜色。利用透明,我们可以这样实现玻璃材质:

Shader "Custom/GlassShader" {
    Properties {
        _MainTint("Main Color", Color) = (1, 1, 1, 1)
        _AlphaVal("Alpha", Range(0, 1)) = 0.1
    }
    SubShader {
        Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType"="Transparent" }
        LOD 200

        CGPROGRAM
        #pragma surface surf BlinnPhong alpha

        fixed4 _MainTint;
        float _AlphaVal;

        struct Input {
            float3 viewDir;
        };

        void surf (Input IN, inout SurfaceOutput o) {
            o.Albedo = _MainTint.rgb;
            o.Alpha = _AlphaVal;
        }
        ENDCG
    } 
    FallBack "Diffuse"
}

此时的效果是这样的,可以看到透明效果,但是它看上去更像两块粗糙的透明的塑料片。

这里写图片描述

给玻璃增加反射效果

为了表现这是光滑的玻璃而非塑料,我们增加反射属性,利用天空盒实现简单的反射效果,此时的代码是这样的:

Shader "Custom/GlassShader" {
    Properties {
        _MainTint("Main Color", Color) = (1, 1, 1, 1)
        _AlphaVal("Alpha", Range(0, 1)) = 0.1
        _CubeMap("Sky Box", CUBE) = ""{}
        _ReflPower("Reflect Power", Range(0, 1)) = 1
    }
    SubShader {
        Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType"="Transparent" }
        LOD 200

        CGPROGRAM
        #pragma surface surf BlinnPhong alpha

        fixed4 _MainTint;
        float _AlphaVal;
        samplerCUBE _CubeMap;
        float _ReflPower;

        struct Input {
            float3 worldRefl;
            float3 viewDir;
        };

        void surf (Input IN, inout SurfaceOutput o) {
            half4 s = texCUBE(_CubeMap, IN.worldRefl);
            o.Albedo = _MainTint.rgb;
            o.Emission = s.rgb * _ReflPower;
            o.Alpha = _AlphaVal;
        }
        ENDCG
    } 
    FallBack "Diffuse"
}

这时候玻璃就有了反射效果,尤其是当我们从不同角度看的时候,会看到玻璃反射了场景中的景象,当然这其实是假的,那来自我们指定的天空盒。

这里写图片描述

给玻璃增加菲涅尔效果

曾经说到过菲涅尔菲先生的效果非常不错,可以根据视角控制反射的强弱。我们的玻璃当然也可以应用这种效果:

Shader "Custom/GlassShader" {
    Properties {
        _MainTint("Main Color", Color) = (1, 1, 1, 1)
        _AlphaVal("Alpha", Range(0, 1)) = 0.1
        _CubeMap("Sky Box", CUBE) = ""{}
        _ReflPower("Reflect Power", Range(0, 1)) = 1
        _FresnelPower("Fresnel Power", Range(0.1, 5)) = 2
    }
    SubShader {
        Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType"="Transparent" }
        LOD 200

        CGPROGRAM
        #pragma surface surf BlinnPhong alpha

        fixed4 _MainTint;
        float _AlphaVal;
        samplerCUBE _CubeMap;
        float _ReflPower;
        float _FresnelPower;

        struct Input {
            float3 worldRefl;
            float3 viewDir;
        };

        void surf (Input IN, inout SurfaceOutput o) {
            float rim = 1.0 - max(0, dot(o.Normal, normalize(IN.viewDir)));
            rim = pow(rim, _FresnelPower);
            half4 s = texCUBE(_CubeMap, IN.worldRefl);
            o.Albedo = _MainTint.rgb;
            o.Emission = s.rgb * _ReflPower * rim;
            o.Alpha = _AlphaVal;
        }
        ENDCG
    } 
    FallBack "Diffuse"
}

下面上本次的最终效果图:

这里写图片描述

结束语

掌握了一些基本的Shader知识以后,剩下的就是继续深入研究和利用已有的知识实现想要的效果,Shader是灵活的,我们完全可以根据自己的想法去实现想要材质。就算有人觉得效果不好,也可以悄悄告诉他:“这是艺术…”。


版权声明:本文为dbtxdxy原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。