深入了解Unity中LineRenderer与TrailRenderer

LineRender和TrailRender是两个好东西,很多Unity拖尾特效都会使用到它们。一些简单的介绍可以参见官方的API文档。

在这里探讨一下它们具体的渲染方式,而后给出一些Shader以便更好地控制它们。

创建LineRender

LineRender是一个以顶点去控制渲染尺寸和位置的条带,顶点个数和具体坐标我们自己可以完全操控。
首先我们需要建立了一个GameObject,然后添加LineRenderer组件,然后填入一下参数:

LineRenderer参数

其实就是一个沿着X方向延展的一组顶点。然后新建一个材质,并把它拖入Materials。
由于当前你使用的是默认材质,所以目前只能获得以下的样子:

显示

就是一个矩形而已。

修改LineRenderer

首先,我们需要一张资源图片,大概是这样:

贴图

这个图片使用PSD制作一下,里面白色部分代表将来要在条带中显露出来的部分,黑色则是透明的部分。只有黑白两种颜色即可。注意要加入通道,即把这个黑白图片在PSD中新建一层透明通道,并且粘贴进去。最后让你的通道看起来是这样:

贴图通道

为什么只要黑白图,不需要颜色?解释一下:
我们用这个素材来构成条带的主要轮廓,而显示的色彩由其它参数控制,所以这里只需要黑白图就可以了。

开始写Shader

属性部分,就是一张贴图就可以了。

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

Tags部分,我们需要设定处于半透明渲染队列,并且设定Alpha混合的模式,就是用最常见的Alpha混合的模式即可。

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

由于我们不需要光照,也不希望受到光照的影响,所以我们写一个直接返回原色的光照方程来避免默认的光照处理。同时,为了避免产生光照部分的Pass,添加noforwardadd参数,这样我们的渲染就只需要一个Pass。

CGPROGRAM        #pragma surface surf NoLight vertex:vert alpha noforwardadd        //光照方程,名字为Lighting接#pragma suface后的光照方程名称 
          //lightDir :顶点到光源的单位向量        //viewDir  :顶点到摄像机的单位向量   
        //atten       :关照的衰减系数           float4 LightingNoLight(SurfaceOutput s, float3 lightDir,half3 viewDir, half atten) 
          { 
               float4 c ; 
               c.rgb =  s.Albedo;
              c.a = s.Alpha; 
            return c; 
          }

接下来是顶点着色器代码,我们只要将系统传递过来顶点颜色和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来设定整个条带的颜色和透明度了。

使用之前的贴图和这个Shader,修改之前的材质。最终这个条带变成这样:

最终的条带

完整的LineRenderer的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       :关照的衰减系数           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很相似,又有些不同。不同之处在于:
首先,它的顶点构成是动态的,每帧你需要将产生TrailRenderer的GameObject移动到不同的位置,这样它会自动连接成一个轨迹。
其次,它由五个颜色值来进行控制整个条带的颜色变化,但是不像LineRenderer,在运行时你并不能修改这些颜色值,因为它的API中没有访问这五个颜色的方法,但是我们仍然可以通过Shader来进行改变。
记住最重要的一点就是,它和LineRenderer一样,都是把一组颜色值写入了顶点颜色,我们只要读取顶点颜色即可。
为了整体控制尾迹的颜色显示,我们增加一个主控制颜色,修改上面那个Shader。

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

最后,在表面着色器中进行相应的修改

        void surf (Input IN, inout SurfaceOutput o) 
        {
            half4 c = tex2D (_MainTex, IN.uv_MainTex);            //c.a为贴图上的透明度,使用它构成条带的图形轮廓            //_MainCol.a为主颜色的透明度,用于对整个条带透明度控制            //IN.vertColor.a由顶点颜色获得,由Colors数组设置,用于控制条带不同位置的透明度度变化
            o.Alpha = c.a * _MainCol.a* IN.vertColor.a;            //_MainCol.rgb为主颜色的颜色值,用于显示主颜色部分            //IN.vertColor.rgb为顶点颜色的颜色值,由Colors数组设置,用于控制条带不同位置的颜色变化
            o.Albedo = _MainCol.rgb*IN.vertColor.rgb;
        }

这样,我们可以通过主控制颜色的变化来控制整体尾迹随着时间的颜色变化。而条带上颜色不同位置的变化,则由那五个颜色值进行控制。当我们只需要显示一个纯色条带时,将五个颜色都设置为白色和变化的透明度即可。
最后,TrailRender的显示效果如下:

TrailRender

当然你需要一个脚本来控制TrailRender所在的GameObject的旋转,代码相对简单。(BaseBehavior类的实现可以参见我的其它文章)

public class TrailRendererGen : BaseBehavior 
{
    [SerializeField][Tooltip("旋转角速度")]    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);
    }
}

完整的TailRenderer的Shader

Shader "AndrewBox/TrailRenderer" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _MainCol ("Self Color Value", Color) = (1,1,1,1)
    }
    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       :关照的衰减系数           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 _MainCol;        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);            //c.a为贴图上的透明度,使用它构成条带的图形轮廓            //_MainCol.a为主颜色的透明度,用于对整个条带透明度控制            //IN.vertColor.a由顶点颜色获得,由Colors数组设置,用于控制条带不同位置的透明度度变化
            o.Alpha = c.a * _MainCol.a* IN.vertColor.a;            //_MainCol.rgb为主颜色的颜色值,用于显示主颜色部分            //IN.vertColor.rgb为顶点颜色的颜色值,由Colors数组设置,用于控制条带不同位置的颜色变化
            o.Albedo = _MainCol.rgb*IN.vertColor.rgb;
        }

        
        ENDCG
    } 
    FallBack "Diffuse"}

总结

最终,我们可以完整控制两种Renderer的渲染了,最重要的事情再说一遍,就是它们的Color设定都写入了顶点颜色,我们可以通过读取顶点颜色来完成自己想要的渲染效果。



本文为博主原创文章,欢迎转载。请保留博主链接http://blog.csdn.net/andrewfan

时间: 2024-11-04 17:19:48

深入了解Unity中LineRenderer与TrailRenderer的相关文章

在Unity中使用贝塞尔曲线(转)

鼎鼎大名的贝塞尔曲线相信大家都耳熟能详.这两天因为工作的原因需要将贝塞尔曲线加在工程中,那么MOMO迅速的研究了一下成果就分享给大家了哦.贝塞尔曲线的原理是由两个点构成的任意角度的曲线,这两个点一个是起点,一个是终点.在这条曲线之上还会有两个可以任意移动的点来控制贝塞尔曲线的角度.如下图所示,点1 和点4 就是起点和终点,点2 和点3 就是控制曲线角度的两个动态点. 如下图所示.使用拖动条来让曲线发生旋转,大家会看的更加清晰.目前我们看到的被塞尔曲线是在平面中完成的,其实贝塞尔曲线是完全 支持3

Unity中做放大镜 效果

孙广东  2015.8.16 事实上和 小地图都几乎相同了. 还是要借助 还有一个相机 目的: 这篇文章的主要目的是  要给你一个想法  怎样做放大境效果 . 在unity中能够简单的实现放大镜效果啊 . 那么如今就来一步一步实现这个: 创建一个摄像机对象.设置 projection 类型为 perspective 或者 orthographic. 设置相机的 orthographicSize 或者 fieldOfView   (依赖于相机的 projection 类型 ). 设置其 pixel

unity中射线碰撞检测总结

这阵子通过看视频,看书对unity中射线碰撞检测,有了一些了解,这里我把它总结一下写下来,希望能帮助到你们,也希望通过各位大神来指正不足之处: 射线碰撞检测,就是由某一物体发射出一道射线,射线碰撞到物体之后,可以得到该物体的相关信息,然后就可以对该物体进行一些操作的过程了.PS:个人见解: 射线的发射分为可见和不可见,可见的情况就是在游戏当中你可以看到射线,而不可见就是游戏运行时,你只可以在Scene试图下观察到它,而这到射线又是存在的: 而其实两者区别不大,关键是看你怎么用它了: 下面先看看不

Unity中Mesh分解与边缘高亮加上深度检测

一个比较简单的需求,不过遇到些坑,记录下. 房间有多个模型,每个模型可能多个SubMesh,点击后,需要能具体到是那个SubMesh,并且在这个SubMesh上显示边缘高光,以及能个性这单个SubMesh对应的Material.如一个桌子的Mesh,其实有二个材质,分别对应二个SubMesh,一个桌面和一个桌脚,点击桌面后,只有这个桌面高光,而不是整个桌子,并且能单独更换这个桌面的Material. 我们知道Unity中,Mesh和Ogre一样,也是可以有多个SubMesh,每个SubMesh有

NGUI研究院之在Unity中使用贝塞尔曲线(六)[转]

鼎鼎大名的贝塞尔曲线相信大家都耳熟能详.这两天因为工作的原因需要将贝塞尔曲线加在工程中,那么MOMO迅速的研究了一下成果就分享给大家了哦.贝塞尔曲线的原理是由两个点构成的任意角度的曲线,这两个点一个是起点,一个是终点.在这条曲线之上还会有两个可以任意移动的点来控制贝塞尔曲线的角度.如下图所示,点1 和点4 就是起点和终点,点2 和点3 就是控制曲线角度的两个动态点. 如下图所示.使用拖动条来让曲线发生旋转,大家会看的更加清晰.目前我们看到的被塞尔曲线是在平面中完成的,其实贝塞尔曲线是完全支持3D

NGUI研究之在Unity中使用贝塞尔曲线

鼎鼎大名的贝塞尔曲线相信大家都耳熟能详.这两天因为工作的原因需要将贝塞尔曲线加在工程中,那么我迅速的研究了一下成果就分享给大家了哦.贝塞尔曲线的原理是由两个点构成的任意角度的曲线,这两个点一个是起点,一个是终点.在这条曲线之上还会有两个可以任意移动的点来控制贝塞尔曲线的角度.如下图所示,点1 和点4 就是起点和终点,点2 和点3 就是控制曲线角度的两个动态点.上一章分享了开发项目的一些使用心得比较细节对新手很有用可以看下. 如下图所示.使用拖动条来让曲线发生旋转,大家会看的更加清晰.目前我们看到

如何在unity中实现拖尾效果

在制作游戏过程中会出现鼠标滑动的实现,而为啦增强视觉效果,往往会添加拖尾或者鼠标点击的特效,接下来就说说在unity中如何实现拖尾效果,首先unity中有个组件,叫TrailRenderer,在Component ——> Effect——>TrailRenderer中添加,根据自己需要的效果设置自己需要的颜色,然后还有相应的曲线和拖尾长度,来实现自己需要的效果,接下来上代码 public TrailRenderer m_CollectTrail = null; #if UNITY_EDITOR

在Unity中使用事件/委托机制(event/delegate)进行GameObject之

欢迎来到unity学习.unity培训.unity企业培训教育专区,这里有很多U3D资源.U3D培训视频.U3D教程.U3D常见问题.U3D项目源码,[狗刨学习网]unity极致学院,致力于打造业内unity3d培训.学习第一品牌. 一对多的观察者模式机制有什么缺点? 如果你对如何在Unity中使用事件/委托机制还不太了解,建议您查看我的前一篇文章:[Unity3D技巧]在Unity中使用事件/委托机制(event/delegate)进行GameObject之间的通信 在前一篇博客里面,我们写到

unity中三种调用其他脚本函数的方法

第一种,被调用脚本函数为static类型,调用时直接用  脚本名.函数名().很不实用-- 第二种,GameObject.Find("脚本所在物体名").SendMessage("函数名");  此种方法可以调用public和private类型函数 第三种,GameObject.Find("脚本所在物体名").GetComponent<脚本名>().函数名();此种方法只可以调用public类型函数 unity中三种调用其他脚本函数的