unity实现3D物体的残影效果
程序员文章站
2022-07-13 22:31:19
...
很久之前我写过一篇用对象池等知识实现的2D的残影效果
好像有挺多小伙伴看的添加链接描述
然后这几天我有入门了一下shader 接触了透明的效果
之后我就飘了 想实现一下3D残影的效果
但是这个仅限于unity自带的规则物体 我这用的是球(sphere)
而且我写的代码没有做优化 可能有点混乱
老规矩我还是给出demo吧
我这里的想法是 我弄几个小球 让后边的小球跟着前边的走
前边的后边 后边的就怎么走
这个我们利用unity的特性很容易可以实现
private void FixedUpdate()
{
transform.position = LastObject.position;
}
这样就很容易的实现了小球的跟随效果
这时候我们就想到了透明的效果了
我们要用shader自己去写一个材质
Shader "Custom/Chapter"
{
Properties{
_MainTex("Main Texture",2D) = "white"{}
_BaseColor("Base Color",Color) = (1.0,1.0,1.0,1.0)
_AlphaScale("Alpha Threshold",Range(0,1)) = 1
}
SubShader{
Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
//记住Transparent就完事了
pass{
ZWrite On
ColorMask 0 // 控制该Pass不输出任何颜色
}
pass{
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
//关闭深度写入,同时开启混合。这里我们的混合因子选择了SrcAlpha 和OneMinueSrcAlpha
//这两个计算因子最终可以得到半透明混合的效果。
Tags{"LightMode"="ForwardBase"}
//不变
CGPROGRAM
#pragma vertex Vertex
#pragma fragment Pixel
#include "Lighting.cginc"
struct vertexInput{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
sampler2D _MainTex;
fixed4 _BaseColor;
fixed _AlphaScale;
vertexOutput Vertex(vertexInput v){
vertexOutput o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex);
o.uv = v.texcoord;
return o;
}
fixed4 Pixel(vertexOutput i):SV_TARGET{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed3 albedo = tex2D(_MainTex,i.uv).xyz * _BaseColor.xyz;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = _LightColor0.xyz * albedo * saturate(dot(worldNormal,lightDir));
return fixed4(diffuse + ambient,_AlphaScale);
}
ENDCG
}
}
}
然后我们可以通过c#中的方法来修改透明度 从而实现残影的效果
private void Start()
{
lattmat = GetComponent<Renderer>().material;
}
private void Update()
{
lattmat.SetFloat("_AlphaScale", alpyh);
}
之后我们就要思考 怎么能把后边的球联系起来
public followobject lastscript;//上一个物体的脚本
public Transform LastObject;//上一个物体
private Material lattmat;//本物体的材质
public float alpyh;//设置的透明度
之后我们在unity中赋值
这里的赋值都上上一个物体
然后我给出完整的源码 给大家参考
后边子物体的脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class followobject : MonoBehaviour
{
public followobject lastscript;//上一个物体的脚本
public Transform LastObject;//上一个物体
private Material lattmat;//本物体的材质
public float alpyh;//设置的透明度
private void Start()
{
lattmat = GetComponent<Renderer>().material;
}
private void Update()
{
lattmat.SetFloat("_AlphaScale", alpyh);
}
private void FixedUpdate()
{
transform.position = LastObject.position;
if (lastscript == null)
{
alpyh = ConShader.Instance.a;
}
else
{
alpyh = lastscript.alpyh;
}
}
}
可键盘控制的物体
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ConShader : MonoBehaviour
{
public float a = 1;
public bool isstart = false;
public static ConShader Instance;
private void Awake()
{
Instance = this;
}
private void Update()
{
transform.Translate(new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")) * Time.deltaTime * 20);
if (isstart)
{
a -= Time.deltaTime;
}
if (a < 0)
{
isstart = false;
a = 0;
}
if (Input.GetKeyDown(KeyCode.Space))
{
a = 1;
isstart = true;
}
}
}
shader源码
Shader "Custom/Chapter"
{
Properties{
_MainTex("Main Texture",2D) = "white"{}
_BaseColor("Base Color",Color) = (1.0,1.0,1.0,1.0)
_AlphaScale("Alpha Threshold",Range(0,1)) = 1
}
SubShader{
Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
//记住Transparent就完事了
pass{
ZWrite On
ColorMask 0 // 控制该Pass不输出任何颜色
}
pass{
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
//关闭深度写入,同时开启混合。这里我们的混合因子选择了SrcAlpha 和OneMinueSrcAlpha
//这两个计算因子最终可以得到半透明混合的效果。
Tags{"LightMode"="ForwardBase"}
//不变
CGPROGRAM
#pragma vertex Vertex
#pragma fragment Pixel
#include "Lighting.cginc"
struct vertexInput{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
sampler2D _MainTex;
fixed4 _BaseColor;
fixed _AlphaScale;
vertexOutput Vertex(vertexInput v){
vertexOutput o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex);
o.uv = v.texcoord;
return o;
}
fixed4 Pixel(vertexOutput i):SV_TARGET{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed3 albedo = tex2D(_MainTex,i.uv).xyz * _BaseColor.xyz;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = _LightColor0.xyz * albedo * saturate(dot(worldNormal,lightDir));
return fixed4(diffuse + ambient,_AlphaScale);
}
ENDCG
}
}
}
希望我所写的对大家有所帮助
如果有问题可以联系我 主页有我的联系方式
上一篇: 用于保存和加载列表框数据的类