前阵子组长给我提了个需求,要实现角色人物的残影。我百度google了一下,发现可以用两种方式实现这个效果:1.记录前几帧的人物位置,将其传入shader中,对每个位置进行一个pass渲染。2. 通过相机的targetRender,记录前几帧的人物的影像,然后通过后处理混合上去。

这里先介绍方法1,先看效果:

残影用了alpha混合的方法,将它们变得透明。

先列出shader代码:

Shader "Custom/Ghost" {
Properties {
_MainTex ("Main Tex", 2D) = "white" {}
_Offset0 ("Offset 0", vector) = (, , , ) // 这里只显示4个残影,所以传入4个偏移值
_Offset1 ("Offset 1", vector) = (, , , )
_Offset2 ("Offset 2", vector) = (, , , )
_Offset3 ("Offset 3", vector) = (, , , )
} CGINCLUDE
#include "UnityCG.cginc" sampler2D _MainTex; float4 _Offset0;
float4 _Offset1;
float4 _Offset2;
float4 _Offset3; struct v2f {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};

    // 在shader中要渲染自身,以及4个残影,所以要定义5个不同的vert函数
v2f vert_normal(appdata_base v) { // 渲染自身的vert函数
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord;
return o;
}
    // 渲染4个残影的vert函数
v2f vert_offset_1(appdata_base v) {
v2f o;
float4 pos = mul(_Object2World, v.vertex);
o.pos = mul(UNITY_MATRIX_VP, pos + _Offset0);
o.uv = v.texcoord;
return o;
} v2f vert_offset_2(appdata_base v) {
v2f o;
float4 pos = mul(_Object2World, v.vertex);
o.pos = mul(UNITY_MATRIX_VP, pos + _Offset1);
o.uv = v.texcoord;
return o;
} v2f vert_offset_3(appdata_base v) {
v2f o;
float4 pos = mul(_Object2World, v.vertex);
o.pos = mul(UNITY_MATRIX_VP, pos + _Offset2);
o.uv = v.texcoord;
return o;
} v2f vert_offset_4(appdata_base v) {
v2f o;
float4 pos = mul(_Object2World, v.vertex);
o.pos = mul(UNITY_MATRIX_VP, pos + _Offset3);
o.uv = v.texcoord;
return o;
}
    
     
    // 这里只定义了两个frag函数,分别是渲染自身,以及残影的
float4 frag_normal(v2f i) : COLOR {
return tex2D(_MainTex, i.uv);
} float4 frag_color(v2f i) : COLOR { // 将残影的alpha值设为0.5
float4 c;
c = tex2D(_MainTex, i.uv);
c.w = 0.5;
return c;
}
ENDCG SubShader { // 这里用4个pass来渲染残影,第5个pass渲染自身
Pass { // 从最远的开始渲染
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM
#pragma vertex vert_offset_4
#pragma fragment frag_color
ENDCG
} Pass {
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM
#pragma vertex vert_offset_3
#pragma fragment frag_color
ENDCG
} Pass {
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM
#pragma vertex vert_offset_2
#pragma fragment frag_color
ENDCG
} Pass {
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM
#pragma vertex vert_offset_1
#pragma fragment frag_color
ENDCG
} Pass { // 渲染自身,这时要开启 ZWrite
Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM
#pragma vertex vert_normal
#pragma fragment frag_normal
ENDCG
}
}
FallBack "Diffuse"
}

看上去挺简单的。这里要注意的一点是,从c#脚本获取的offset值,是在世界坐标中获取的,所以在计算偏移时,要先将坐标转到世界坐标。

float4 pos = mul(_Object2World, v.vertex);
o.pos = mul(UNITY_MATRIX_VP, pos + _Offset0);

接着显示C#脚本:

using UnityEngine;
using System.Collections;
using System.Collections.Generic; [ExecuteInEditMode]
public class Ghost : MonoBehaviour {
public Shader curShader;
private List<Vector3> offsets = new List<Vector3>(); // 存储前几帧的坐标
private List<Material> mats = new List<Material>(); // 存储人物的材质,用于给shader传参数
// Use this for initialization
void Start ()
{
offsets.Add(transform.position);
offsets.Add(transform.position);
offsets.Add(transform.position);
offsets.Add(transform.position); var skinMeshRenderer = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();
foreach (var mr in skinMeshRenderer)
mats.Add(mr.material); var meshRenderer = gameObject.GetComponentsInChildren<MeshRenderer>();
foreach (var mr in meshRenderer)
mats.Add(mr.material); foreach (var mat in mats)
mat.shader = curShader;
} // Update is called once per frame
void Update () {
foreach (var mat in mats) // 每帧将之前的位置传入shader中
{
mat.SetVector("_Offset0", offsets[] - transform.position);
mat.SetVector("_Offset1", offsets[] - transform.position);
mat.SetVector("_Offset2", offsets[] - transform.position);
mat.SetVector("_Offset3", offsets[] - transform.position);
} offsets.Add(transform.position);
offsets.RemoveAt();
}
}

就这样,将C#脚本拖到GameObject身上就可以了

总结:

这个方法相对简单,问题就是,残影是和自身动作是一样的。如果要做成残影保留之前的动作,就需要记录动作参数,或者是直接保存前几帧的RenderTexture。

Unity Shader : Ghost(残影) v1的更多相关文章

  1. unity制作人物残影-绘制的方法

    这里是利用skinnedMeshRenderer原理做的 所以脚本需要挂在带这个组件的模型上 模型shader 必须要有个_Color参数属性,并且这个值可以调节颜色,会改变人物整体的透明度 [代码下 ...

  2. Unity运动残影技能

    残影实现: 1.List<DrawMesh> list,此list中包含某一帧动画模型网格.材质 2.每过一段时间就将运动物体的模型add到list中(优化:未实现,网格合并) 3.Lat ...

  3. cocos2dx - shader实现任意动画的残影效果

    本节主要讲利用cocos2dx机制实现opengl es shader脚本的绘制 这里先看下最终效果:                      这里分别实现了灰度效果及残影的效果. 一.绘制基类 这 ...

  4. Unity角色残影特效

    残影特效在网上有很多例子,比如这个,我参考着自己整合了一下,算是整合了一个比较完整且特别简单易用的出来,只需要一个脚本挂上去无需任何设定就能用. 这里只针对SkinnedMeshRenderer的网格 ...

  5. 【Unity Shader】从NDC(归一化的设备坐标)坐标转换到世界坐标的数学原理

    从NDC(归一化的设备坐标)坐标转换到世界坐标要点 参考资料 How to go from device coordinates back to worldspace http://feepingcr ...

  6. Unity3D手游开发日记(8) - 运动残影效果

    2D游戏的残影很简单,美术做序列帧图片就行了,那么3D游戏的残影美术做不了,得靠程序员动态创建模型来处理. 实现原理也很简单: 1.间隔一定时间创建一个残影模型 GameObject go = Gam ...

  7. Unity3D-Shader-人物残影效果

    [旧博客转移 - 2016年1月7日 00:24 ] 前面的话 上一篇讲了一下人物边缘发光效果,链接: Unity-ShaderLab-实现X光效果,这次我们利用这个Shader来实现人物残影效果 先 ...

  8. Unity Shader - 消融效果原理与变体

    基本原理与实现 主要使用噪声和透明度测试,从噪声图中读取某个通道的值,然后使用该值进行透明度测试. 主要代码如下: fixed cutout = tex2D(_NoiseTex, i.uvNoiseT ...

  9. Unity Shader 玻璃效果

    一个玻璃效果主要分为两个部分,一部分是折射效果的计算,另一部分则是反射.下面分类进行讨论: 折射: 1.利用Grass Pass对当前屏幕的渲染图像进行采样 2.得到法线贴图对折射的影响 3.对采集的 ...

随机推荐

  1. 解决tableView分割线左边不到边的情况

    //解决tableView分割线左边不到边的情况//    if ([tableView respondsToSelector:@selector(setSeparatorInset:)]) {//  ...

  2. LintCode "Subarray Sum II"

    Sliding window doesn't work. So it is a typical partial_sum base solution. As below. However if you ...

  3. IntelliJ IDEA安装AngularJS插件

    Settings→Plugins→Install JetBrains plugins... 输入an后选择AngularJS,然后点击Install进行安装 按照提示重启IDEA 下图为插件管理窗口, ...

  4. bzoj3163: [Heoi2013]Eden的新背包问题

    Description “寄没有地址的信,这样的情绪有种距离,你放着谁的歌曲,是怎样的心心静,能不能说给我听.”失忆的Eden总想努力地回忆起过去,然而总是只能清晰地记得那种思念的感觉,却不能回忆起她 ...

  5. Redis简单使用方法说明

    安装 www.redis.io下载安装包tar zxvf redis.tar.gzcd redismakecd src && make install移动文件,便于管理:mkdir - ...

  6. 在Visual Studio 2010/2012中 找不到创建WebService的项目模板

    参考文章: http://blog.sina.com.cn/s/blog_6d545999010152wb.html 在 Visual Studio 2010 或者2012的新建 Web 应用程序或者 ...

  7. spark IDEA开发环境搭建及运行问题

    下图是例子: 还用说么,引入相关jar包(等下再一一说明)  包括scala,spark-assembly-1.4.1-hadoop2.5.0-cdh5.2.1.jar(按照你的spark和hadoo ...

  8. bootstrap-响应式图片、辅助类样式

    响应式图片: <div class="container"> <!-- img-responsive 响应式图片 --> <div class=&qu ...

  9. ios模拟器未能安装此应用程序

    网上介绍了很多方法,觉得有些不太靠谱.这里只解释我试验过的最简单最粗暴的方法: 删除模拟器上旧的APP 以外,也可以做 CLEAN (cmd+shift+K) 把旧的build 删掉.

  10. 原密码忘了,重置MAC开机密码

    如果登陆密码忘了,或者你接手了一台前任同事的MAC,而他设了密码没告诉你,你可以这样: 1.重启MAC,然后在启动时按下:CMD+S 2.进入命令行格式后输入:fsck -y (file system ...