Unity 引擎做残影效果——3、顶点偏移方式

这篇具有很好参考价值的文章主要介绍了Unity 引擎做残影效果——3、顶点偏移方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Unity实现残影效果


  大家好,我是阿赵。
  继续讲Unity引擎的残影做法。这次的残影效果和之前两种不太一样,是通过顶点偏移来实现的。
  具体的效果是这样:
Unity 引擎做残影效果——3、顶点偏移方式,Unity引擎Shader效果,unity,游戏引擎,残影,顶点偏移Unity 引擎做残影效果——3、顶点偏移方式,Unity引擎Shader效果,unity,游戏引擎,残影,顶点偏移

  与其说是残影,这种效果更像是移动速度很快时造成的速度线,所以在移动过程中的效果还是非常好的,截图的感觉没有视频的感觉那么有冲击力。

一、原理介绍

1、顶点偏移

  这个做法很简单,在c#里面对比当前帧和上一帧的坐标,如果坐标有变化,就把两个坐标相减,算出一个世界空间坐标的向量出来,并做标准化处理。
  得到了这么一个向量之后,就可以把它传入到shader里面了。
  既然是顶点偏移,那么肯定是在顶点着色器程序里面做修改了。不过这里有个比较值得注意的问题。一般写shader的时候,如果没有特殊的需要,我们都是直接把顶点坐标从物体局部坐标直接就转换到裁剪空间了,比如使用Untiy提供的方法:

UnityObjectToClipPos(v.vertex);

  但在这个例子里面,我们从c#传入的是世界空间坐标的向量,所以我们不能通过模型局部坐标或者裁剪空间去叠加这个偏移向量,而应该在同样的世界坐标上面去偏移。

float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
worldPos += _MoveDir * _MoveDis;

  其中_MoveDir就是标准化后的移动向量, _MoveDis是用于控制偏移距离的变量。
  这个时候,可以看到,整个模型都在拉伸了
Unity 引擎做残影效果——3、顶点偏移方式,Unity引擎Shader效果,unity,游戏引擎,残影,顶点偏移

  但这种效果明显不是我们想要的。

2.控制偏移的范围

  我们想要的效果是怎样的呢?是不是应该是移动的过程中,前面的部分是不变形的,只有最后一点位置出现拉伸?
  怎么去控制拉伸的范围呢?其实很简单,假如我们把刚才那个移动的向量想象成是灯光,就可以求出这样的一个效果:
Unity 引擎做残影效果——3、顶点偏移方式,Unity引擎Shader效果,unity,游戏引擎,残影,顶点偏移

  很明显的,模型高亮的部分,其实就是我们想拉伸的方向了。所以,其实很简单,把移动方向和模型的法线做点乘,就可以求出一个我们想偏移的范围了。
  不过现在高亮的部分还是有点多,所以我们用一个power运算,让对比度变得更高,就变成了下面这个情况。
Unity 引擎做残影效果——3、顶点偏移方式,Unity引擎Shader效果,unity,游戏引擎,残影,顶点偏移

  现在,白色的部分只有很小的范围了。接下来就对这个白色的范围做顶点偏移:
Unity 引擎做残影效果——3、顶点偏移方式,Unity引擎Shader效果,unity,游戏引擎,残影,顶点偏移

  基本上就出现了我们想要的效果了。

二、优缺点

1、优点

  首先,之前介绍的不管是BakeMesh还是屏幕后处理,都是基于对模型的多次渲染上的,所以性能上并不那么友好。
  用顶点偏移的方式,并没有太多额外的计算量,所以从性能上来说,它是比前两种方式都要好的。
  然后,顶点偏移这种手段,其实是一种非常简单的技术含量比较低的手段,难点是在于你怎样想出这个办法而已,所以知道了方法之后,其实非常容易就能实现了。

2、缺点

  这个做法的缺点也是很明显的。
  首先,它不是真正的残影效果,只是速度线的类似效果,所以我个人感觉只适合用于特定的风格里面,比如卡通之类。如果写实风格的游戏用这种效果可能不太行。
  然后,由于是要对模型做顶点偏移,那么就要意味着需要修改模型原有的Shader了。对于比较正规的团队来说,这问题不大,因为项目里面每个Shader都应该是经过TA的定制的,需要统一加入一些元素是很简单的。
  但对于不那么正规的团队,甚至是纯美术人员组成的团队来说,说不定已经在用的Shader都是从不知道哪个网站上面复制下来的,要统一修改,难度会非常大。
  所以,如果想使用这种技术手段,还是要先考虑一下自己的实际情况的。

三、代码

  同样的,只是demo,所以代码只是在于实现部分,没有过多优化。文章来源地址https://www.toymoban.com/news/detail-624868.html

1、C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveVertexOffsetCtrl : MonoBehaviour
{
    public float moveDis = 1;
    private bool isMove = false;
    private Vector3 oldPos = Vector3.zero;
    public GameObject role;
    private Vector3 moveDir = Vector3.zero;
    private List<Material> matList;
    public float pow = 1;

    // Start is called before the first frame update
    void Start()
    {
        matList = new List<Material>();
        if(role)
        {
            SkinnedMeshRenderer[] renders = role.GetComponentsInChildren<SkinnedMeshRenderer>();
            for(int i = 0;i<renders.Length;i++)
            {
                for(int j = 0;j<renders[i].materials.Length;j++)
                {
                    Material mat = renders[i].materials[j];
                    if (matList.IndexOf(mat) < 0)
                    {
                        matList.Add(mat);
                    }
                }
                
            }
        }
    }

    // Update is called once per frame
    void Update()
    {
        CheckMove();
        SetMaterial();
    }

    private void CheckMove()
    {
        if(role)
        {
            if(Vector3.Distance(role.transform.position,oldPos)>0)
            {
                moveDir =  oldPos - role.transform.position;
                moveDir = moveDir.normalized;
                oldPos = role.transform.position;
                isMove = true;
            }
            else
            {
                isMove = false;
            }
        }
        else
        {
            isMove = false;
        }
    }

    private void SetMaterial()
    {
        if(matList!=null&&matList.Count>0)
        {
            for(int i = 0;i<matList.Count;i++)
            {
                if(isMove==false)
                {
                    matList[i].SetFloat("_MoveDis", 0);
                }
                else
                {
                    matList[i].SetFloat("_MoveDis", moveDis);
                    matList[i].SetVector("_MoveDir", moveDir);
                    matList[i].SetFloat("_MovePow", pow);
                }
            }
        }
    }
}

2、Shader

Shader "azhao/MoveVertexBase"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
		_MoveDir("MoveDir",Vector) = (0,0,0,0)
		_MoveDis("MoveDis",float) = 0
		_MovePow("MovePow",float) = 1

    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag


            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
				half3 normal : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
			float4 _MoveDir;
			float _MoveDis;
			float _MovePow;
            v2f vert (appdata v)
            {
                v2f o;
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
				float3 worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);
				float ndotl = saturate(dot(worldNormal, _MoveDir));
				ndotl = pow(ndotl, _MovePow);
				worldPos += _MoveDir * _MoveDis*ndotl;
				//世界空间顶点坐标转观察空间坐标
				float4 viewPos = mul(UNITY_MATRIX_V, worldPos);
				//观察空间坐标转裁剪空间坐标
				float4 clipPos = mul(UNITY_MATRIX_P, viewPos);
				o.vertex = clipPos;
                return o;
            }

            half4 frag (v2f i) : SV_Target
            {
                // sample the texture
                half4 col = tex2D(_MainTex, i.uv);
                return col;
            }
            ENDCG
        }
    }
}

到了这里,关于Unity 引擎做残影效果——3、顶点偏移方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity Shader学习记录(11) ——透明效果的实现方式

    1 透明效果的两种方法 透明是游戏中经常要使用的一种效果。在实时渲染中要实现透明效果,通常会在渲染模型时控制它的透明通道(Alpha Channel)。当开启透明混合后,当一个物体被渲染到屏幕上时,每个片元除了颜色值和深度值之外,它还有另一个属性一一透明度。 当透明度

    2024年02月07日
    浏览(45)
  • 【游戏开发解答】Unity中对UGUI的Image进行倾斜变形(UGUI | 精灵图 | OnPopulateMesh | 顶点偏移 | 变形)

    本文最终效果 一、前言 嗨,大家好,我是新发。 前同事问了我一个问题,如何将 UGUI 的 Image 进行变形,变成斜斜的, 最直接的就是出图的时候直接就画成斜的,我们不讨论这种情况,这里我们单纯的从技术实现上去思考能不能在 Unity 中通过 UGUI 的 Image 对图片进行倾斜变形

    2024年02月04日
    浏览(56)
  • 【unity实战】用对象池设计制作Dash冲锋残影的效果

    参考原视频链接: 【视频】:https://space.bilibili.com/370283072 注意 :本文为学习笔记记录,推荐支持原作者,去看原视频自己手敲代码理解更加深入 基于上一篇人物移动二段跳进一步优化完善 在Unity中,对象池是一种重复使用游戏对象的技术。使用对象池的好处是可以减少游戏

    2023年04月17日
    浏览(32)
  • Unity引擎修改模型顶点色的工具

    大家好,我是阿赵。   之前分享过怎样通过MaxScript在3DsMax里面修改模型的顶点色。不过由于很多时候顶点色的编辑需要根据在游戏引擎里面的实际情况和shader的情况来动态调整,所以如果能在引擎里面直接修改模型的顶点色,将会方便很多。于是我写了下面这个在Unity引擎

    2024年02月11日
    浏览(45)
  • Unity Shader学习3:透明效果

    Unity中的透明效果由透明通道控制(RGBA中的A),其值为0是完全透明,为1时完全不透明。有两种方法可以实现透明效果: 透明度测试(Alpha Test) 和 透明度混合(Alpha Blend) 。 透明度测试是指通过特定的条件(通常是Alpha通道的值是否超过某个阈值)来判断片元是否透明,只

    2024年01月19日
    浏览(62)
  • Unity用Shader实现边缘光效果

    《自学记录》 1、先创建一个Cube,再创建两个材质球Cube、Unilt 2、再创建一个shader代码UniltShader【Project右键Create-Shader-NewSurfaceShader】把里面原来的代码删除,写入下面的代码 3、把shader UniltShader拖给材质球Unilt 4、把Cube的Mesh Renderer中Materials的Size改为2,然后把材质球Cube、Unilt分

    2024年02月08日
    浏览(46)
  • Unity Shader入门精要学习——透明效果

    要么完全透明,要么完全不透明。 实现简单,实质上是一种剔除机制,通过将不满足条件(通常使用小于某个阈值来判定,一般使用clip方法)的片元舍弃的方法来达到完全透明效果。这些被舍弃的片元不会再进行任何的处理,也不会对颜色缓冲产生任何影响,其余满足条件

    2024年02月17日
    浏览(49)
  • 【Unity Shader】Unity中利用GrabPass实现玻璃效果

    《入门精要》中模拟玻璃是用了Unity里的一个特殊的Pass来实现的,这个Pass就是 GrabPass ,比起上一篇博客实现镜子的方法,这个方法我认为相对复杂,因此在实现之前需要对GrabPass及实现原理做一个更加详细的介绍。 场景物体拜访和贴图完全参考《入门精要》: 以及当前场景

    2024年02月09日
    浏览(49)
  • Unity Shader入门精要 第八章——透明效果

    目录 前言 一、渲染顺序的重要性 二、Unity Shader的渲染顺序 三、透明度测试 1、什么是透明度测试 2、实践 四、透明度混合 1、什么是透明度混合 2、实践  五、开启深度写入的半透明效果 1、实现方法  2、实践 六、ShaderLab的混合命令 1、混合等式和参数 2、混合操作  3、常见

    2024年02月04日
    浏览(45)
  • 【unity shader】水体渲染基础-水下透视效果

    接下来是水体渲染基础的最后一篇,通过水面看到水下的物体,并呈现深度效果。 我们直接搭一个小场景。 增加水面,赋予uv变形的水面材质,并增加透明度的设置。 水体会吸收光线,所以真实的水体并不是完全透明的。此外,水体对不同频率的光吸收率不同,蓝光被吸收

    2024年03月14日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包