UnityShader之法线贴图

这些日子学补数学搞得头都大了

最近想做个小游戏放松下,我会尽可能的详细

在本节中涉及到的数学之前没提到过,但是好在unity已经为我们包装好了一些功能
不需要我们进行重复的计算

法线贴图:也叫凹凸映射,这个很有用,当然,这里介绍的只是基础的NormalMap。随便举个例子好了,在巫师3等大型游戏当中,大家都可以看到高分辨率效果模型,地面服装或者是建筑物,如果这些都让美术建模师们去做的话,那会有两个严重的弊端1.炒鸡繁重的工作量 2.GPU会非常累,。计算量太大了。

因为我们用shader可以将法线贴图中的像素点作为模型的法线,这样我们的光照就会呈现高分辨率的效果,同时保持模型的低面数(低多边形数)

Shader "Example / NormalMapping" 
{
    Properties 
    {
        _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
        //法线贴图
        _NormalTex ("Normal Map", 2D) = "bump" {}
        //显示法线贴图在游戏物体上的高度
        _NormalIntensity ("Normal Map Intensity", Range(0,2)) = 1
    }

    SubShader 
    {
        //指定此着色器的渲染类型,此着色器将渲染非透明物体
        Tags { "RenderType"="Opaque" }
        LOD 200

        //开始CG代码
        CGPROGRAM
        #pragma surface surf Lambert

        //创建与CG内的属性的连接
        sampler2D _NormalTex;
        float4 _MainTint;
        float _NormalIntensity;

        //获取法线贴图的uv坐标
        struct Input 
        {
            float2 uv_NormalTex;
        };

        //表面着色器
        void surf (Input IN, inout SurfaceOutput o) 
        {
            //从法线贴图中获取法线数据
            //tex2D函数会获取到法线贴图的像素点并返回float4
            //用法线解压函数UnpackNormal,并提取法线信息,将float4转换成float3(三维向量)
            float3 normalMap = UnpackNormal(tex2D(_NormalTex, IN.uv_NormalTex));

            //增强法线表现强度,Z方向上不变
            normalMap = float3(normalMap.x * _NormalIntensity, normalMap.y * _NormalIntensity, normalMap.z);

            //给模型应用新的法线数据
            o.Normal = normalMap.rgb;
            o.Albedo = _MainTint.rgb;
            o.Alpha = _MainTint.a;
        }
        ENDCG
    } 
    FallBack "Diffuse"
}

UnityShader之法线贴图_第1张图片

UnityShader之法线贴图_第2张图片

这里有需要注意的地方
UnpackNormal()函数,当你在着色器中使用这个函数的时候,unity将对你提供的法线贴图进行处理,在这个例子里,对法线贴图进行处理后,会将处理后的值返回到表面着色器标准输出结构里(SurfaceOutput)这样,处理后的法线数据就可以在光照函数中使用了,具体怎么使用,让我们看看Lighting.cginc的源码

#if defined(UNITY_SHOULD_SAMPLE_SH) || defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
    #define UNITY_LIGHT_FUNCTION_APPLY_INDIRECT
#endif

inline fixed4 UnityLambertLight (SurfaceOutput s, UnityLight light)
{
    fixed diff = max (0, dot (s.Normal, light.dir));

    fixed4 c;
    c.rgb = s.Albedo * light.color * diff;
    c.a = s.Alpha;
    return c;
}

inline fixed4 LightingLambert (SurfaceOutput s, UnityGI gi)
{
    fixed4 c;
    c = UnityLambertLight (s, gi.light);

    #if defined(DIRLIGHTMAP_SEPARATE)
        #ifdef LIGHTMAP_ON
            c += UnityLambertLight (s, gi.light2);
        #endif
        #ifdef DYNAMICLIGHTMAP_ON
            c += UnityLambertLight (s, gi.light3);
        #endif
    #endif

    #ifdef UNITY_LIGHT_FUNCTION_APPLY_INDIRECT
        c.rgb += s.Albedo * gi.indirect.diffuse;
    #endif

    return c;
}

没错!就是通过SurfaceOutput传进去的,这里只是一部分具有代表性的源码,大家可以去自己的安装目录下查看O(∩_∩)O~~

你可能感兴趣的:(unity3d特效)