深入了解Unity中LineRenderer與TrailRenderer

LineRender和TrailRender是兩個好東西,很多Unity拖尾特效都會使用到它們。一些簡單的介紹可以參見官方的API文檔。
在這里探討一下它們具體的渲染方式,而后給出一些Shader以便更好地控制它們。

最終我們可以實現(xiàn)類似這樣的一個效果:


TrailRenderer.gif

接下來,我們先了解LineRenderer。稍后的TailRenderer情況類似。

創(chuàng)建LineRender

LineRender是一個以頂點去控制渲染尺寸和位置的條帶,頂點個數(shù)和具體坐標我們自己可以完全操控。
首先我們需要建立了一個GameObject,然后添加LineRenderer組件,然后填入一下參數(shù):

LineRenderer參數(shù)

其實就是一個沿著X方向延展的一組頂點。然后新建一個材質(zhì),并把它拖入Materials。
由于當前你使用的是默認材質(zhì),所以目前只能獲得以下的樣子:

顯示

就是一個矩形而已。

修改LineRenderer

首先,我們需要一張資源圖片,大概是這樣:

貼圖

這個圖片使用PSD制作一下,里面白色部分代表將來要在條帶中顯露出來的部分,黑色則是透明的部分。只有黑白兩種顏色即可。注意要加入通道,即把這個黑白圖片在PSD中新建一層透明通道,并且粘貼進去。最后讓你的通道看起來是這樣:

貼圖通道

為什么只要黑白圖,不需要顏色?解釋一下:
我們用這個素材來構(gòu)成條帶的主要輪廓,而顯示的色彩由其它參數(shù)控制,所以這里只需要黑白圖就可以了。

開始寫Shader

屬性部分,就是一張貼圖就可以了。

    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }

Tags部分,我們需要設(shè)定處于半透明渲染隊列,并且設(shè)定Alpha混合的模式,就是用最常見的Alpha混合的模式即可。

        Tags { "RenderType"="Transparent"  "IgnoreProjector"="True"  "Queue"="Transparent"}
        LOD 200
        Blend SrcAlpha OneMinusSrcAlpha

由于我們不需要光照,也不希望受到光照的影響,所以我們寫一個直接返回原色的光照方程來避免默認的光照處理。同時,為了避免產(chǎn)生光照部分的Pass,添加noforwardadd參數(shù),這樣我們的渲染就只需要一個Pass。

CGPROGRAM
        #pragma surface surf NoLight vertex:vert alpha noforwardadd

        //光照方程,名字為Lighting接#pragma suface后的光照方程名稱 
        //lightDir :頂點到光源的單位向量
        //viewDir  :頂點到攝像機的單位向量   
        //atten    :關(guān)照的衰減系數(shù) 
        float4 LightingNoLight(SurfaceOutput s, float3 lightDir,half3 viewDir, half atten) 
        { 
            float4 c ; 
            c.rgb =  s.Albedo;
            c.a = s.Alpha; 
            return c; 
        }

接下來是頂點著色器代碼,我們只要將系統(tǒng)傳遞過來頂點顏色和UV坐標存儲下來,以便于輸入到表面著色器就可。

        sampler2D _MainTex;
        fixed4 _SelfCol;

        struct Input 
        {
            float2 uv_MainTex;
            float4 vertColor;
        };

        void vert(inout appdata_full v, out Input o)
        {
            o.vertColor = v.color;
            o.uv_MainTex = v.texcoord;
        }

最后就是最重要的部分,表面著色器代碼:

        void surf (Input IN, inout SurfaceOutput o) 
        {
            half4 c = tex2D (_MainTex, IN.uv_MainTex);
            o.Alpha = c.a * IN.vertColor.a;
            o.Albedo = IN.vertColor.rgb;
        }

        
        ENDCG

其實也很簡單:
這里我們只是提取了貼圖上的 【像素顏色透明度】 X 【頂點顏色透明度】 作為最終透明度。這樣做的目的就是為了提取貼圖上的輪廓,同時透明度也會受到頂點顏色的影響。
使用【頂點顏色】作為最終顏色。
這樣我們就可以通過LineRenderer的StartColor和EndColor來設(shè)定整個條帶的顏色和透明度了。

使用之前的貼圖和這個Shader,修改之前的材質(zhì)。最終這個條帶變成這樣:

最終的條帶

完整的Shader

Shader "AndrewBox/LineRenderer" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
        Tags { "RenderType"="Transparent"  "IgnoreProjector"="True"  "Queue"="Transparent"}
        LOD 200
        Blend SrcAlpha OneMinusSrcAlpha
        CGPROGRAM
        #pragma surface surf NoLight vertex:vert alpha noforwardadd

        //光照方程,名字為Lighting接#pragma suface后的光照方程名稱 
        //lightDir :頂點到光源的單位向量
        //viewDir  :頂點到攝像機的單位向量   
        //atten    :關(guān)照的衰減系數(shù) 
        float4 LightingNoLight(SurfaceOutput s, float3 lightDir,half3 viewDir, half atten) 
        { 
            float4 c ; 
            c.rgb =  s.Albedo;
            c.a = s.Alpha; 
            return c; 
        }

        sampler2D _MainTex;
        fixed4 _SelfCol;

        struct Input 
        {
            float2 uv_MainTex;
            float4 vertColor;
        };

        void vert(inout appdata_full v, out Input o)
        {
            o.vertColor = v.color;
            o.uv_MainTex = v.texcoord;
        }

        void surf (Input IN, inout SurfaceOutput o) 
        {
            half4 c = tex2D (_MainTex, IN.uv_MainTex);
            o.Alpha = c.a * IN.vertColor.a;
            o.Albedo = IN.vertColor.rgb;
        }

        
        ENDCG
    } 
    FallBack "Diffuse"
}

TrailRenderer

TrailRenderer與LineRenderer很相似,又有些不同。不同之處在于:
首先,它的頂點構(gòu)成是動態(tài)的,每幀你需要將產(chǎn)生TrailRenderer的GameObject移動到不同的位置,這樣它會自動連接成一個軌跡。
其次,它由五個顏色值來進行控制整個條帶的顏色變化,但是不像LineRenderer,在運行時你并不能修改這些顏色值,因為它的API中沒有訪問這五個顏色的方法,但是我們?nèi)匀豢梢酝ㄟ^Shader來進行改變。
記住最重要的一點就是,它和LineRenderer一樣,都是把一組顏色值寫入了頂點顏色,我們只要讀取頂點顏色即可。
為了整體控制尾跡的顏色顯示,我們增加一個主控制顏色,修改上面那個Shader。

    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _MainCol ("Self Color Value", Color) = (1,1,1,1)
    }

最后,在表面著色器中進行相應(yīng)的修改

        void surf (Input IN, inout SurfaceOutput o) 
        {
            half4 c = tex2D (_MainTex, IN.uv_MainTex);
            //c.a為貼圖上的透明度,使用它構(gòu)成條帶的圖形輪廓
            //_MainCol.a為主顏色的透明度,用于對整個條帶透明度控制
            //IN.vertColor.a由頂點顏色獲得,由Colors數(shù)組設(shè)置,用于控制條帶不同位置的透明度度變化
            o.Alpha = c.a * _MainCol.a* IN.vertColor.a;
            //_MainCol.rgb為主顏色的顏色值,用于顯示主顏色部分
            //IN.vertColor.rgb為頂點顏色的顏色值,由Colors數(shù)組設(shè)置,用于控制條帶不同位置的顏色變化
            o.Albedo = _MainCol.rgb*IN.vertColor.rgb;
        }

這樣,我們可以通過主控制顏色的變化來控制整體尾跡隨著時間的顏色變化。而條帶上顏色不同位置的變化,則由那五個顏色值進行控制。當我們只需要顯示一個純色條帶時,將五個顏色都設(shè)置為白色和變化的透明度即可。
最后,TrailRender的顯示效果如下:

TrailRender

當然你需要一個腳本來控制TrailRender所在的GameObject的旋轉(zhuǎn),代碼相對簡單。(BaseBehavior類的實現(xiàn)可以參見我的其它文章)

public class TrailRendererGen : BaseBehavior 
{
    [SerializeField][Tooltip("旋轉(zhuǎn)角速度")]
    protected float m_angle=360;
    protected override void OnInitFirst()
    {
    }

    protected override void OnInitSecond()
    {
    }

    protected override void OnUpdate()
    {
        m_transform.Rotate(Vector3.forward, m_angle*Time.deltaTime);
    }
}

總結(jié)

最終,我們可以完整控制兩種Renderer的渲染了,最重要的事情再說一遍,就是它們的Color設(shè)定都寫入了頂點顏色,我們可以通過讀取頂點顏色來完成自己想要的渲染效果。


本頁完整資源請在我的CSDN博客中獲?。?a target="_blank" rel="nofollow">http://blog.csdn.net/andrewfan
本文為博主原創(chuàng)文章,歡迎轉(zhuǎn)載。請保留博主鏈接http://blog.csdn.net/andrewfan

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容