[Image Effect] 유니티 블러(Blur) 이미지 효과- 02 Trail Renderer 모션벡터 획득
- -
이번 포스팅은
[Blur] 블러 이미지 효과- 01 기본 셰이더 (tistory.com)
[Blur] 텍스쳐 기반 블러 이미지 효과- 01 기본 셰이더
이번 포스트는 세 편으로 나뉩니다. 첫 편인 기본 셰이더에선, 블러 텍스쳐를 활용해 원본의 특정 영역에 원하는 방향으로 모션블러를 주는 방법을 설명하며 두 번째 편에서는, 이 셰이더를 Trail
develop-4-art.tistory.com
이전 포스팅에서 제작한 셰이더를 활용해 트레일 렌더러의 모션벡터 값을 RenderTexture에 저장하는 과정을 다룹니다.
먼저 트레일 렌더러에서 Vertex를 추가하는 특성에 대해 알아볼 필요가 있습니다.
트레일 렌더러는 min vertex distance보다 큰 변화값이 존재하면 새로운 버텍스를 배열의 앞에 추가합니다.
그 후, Time만큼 유지됐다가 삭제가 되기에, 배열의 맨 뒤에 있는 버텍스부터 사라지게 됩니다.
따라서, 기존 버텍스에 담긴 정보는 유지하고 새로운 버텍스를 추가하기 위해선 새로 추가된 버텍스나 사라진 버텍스만큼 정보를 앞 혹은 뒤로 옮기는 작업을 해야합니다.
위를 구현하기 위해 LateUpdate 안에 아래와 같은 코드를 작성했습니다.
// Late Update를 돌때마다 TrailRenderer가 만드는 mesh를 조작하기 쉽도록 다른 mesh에 Bake한다.
_trailRenderer.BakeMesh(meshFilter.sharedMesh);
vertices = meshFilter.sharedMesh.vertices;
var deltaCount = vertices.Length - lastVertexCount;
// 정점의 개수가 늘으면, 설명과 같이 정점 인덱스와 정보를 옮긴다.
if (deltaCount > 0)
{
for (var i = colors.Count - 1; i > 0; i--)
{
if (i - (deltaCount) < 0) break;
// 기존에 존재하던 정점의 정보를 뒤로 미룬다.
}
for (var i = 0; i < deltaCount; i++)
{
// 새로 생긴 정점의 정보를 추가한다.
}
}
else
{
for (var i = 0; i < colors.Count; i++)
{
// 정점이 줄어들어도 큰 변화는 없다.
}
}
// 변경된 정점의 개수를 캐싱한다.
lastVertexCount = meshFilter.sharedMesh.vertexCount;
이제 각 시점별로 추가되는 정점에 정보를 추가해야 합니다. 우리 같은 경우, Vertex Color에 Trail Renderer가 움직인 방향 정보를 담을 것이기에, 과거 위치와 현재 위치에 대한 정보를 비교해 Direction을 얻어 기입합니다.
// Vertex Color 값을 유동적으로 옮겨야 하기에, List에 담는다.
var colors = new List();
meshFilter.sharedMesh.GetColors(colors);
// TrailRenderer가 움직인 방향을 구한다.
dir = (pivotTrans.position - lastPos).normalized;
// 색상은 음수값이 나오면 안되기에, 방향값을 양수만 갖도록 한다.
dir += Vector3.one;
vertices = meshFilter.sharedMesh.vertices;
var deltaCount = vertices.Length - lastVertexCount;
if (deltaCount > 0)
{
if (lastColors.Count == 0) lastColors = colors;
for (var i = colors.Count - 1; i > 0; i--)
{
if (i - (deltaCount) < 0) break;
// 마지막으로 기억되어있는 color의 값을 다 뒤로 미룬다.
colors[i] = lastColors[i - (deltaCount)];
}
for (var i = 0; i < deltaCount; i++)
{
var ratio = (float)i / vertices.Length;
var multiplier = mixCurve.Evaluate(ratio);
// 앞서, 양수로 만들기 위해 1만큼씩 각 요소에 더했기에 반으로 나눠
// 0~1사이의 값으로 만든다.
var color = new Color(.5f * dir.x, .5f * dir.y, 1f, 1f);
color = Color.Lerp(colors[i], color, multiplier);
colors[i] = color;
}
}
else
{
for (var i = 0; i < colors.Count; i++)
{
colors[i] = lastColors[i];
}
}
lastVertexCount = meshFilter.sharedMesh.vertexCount;
lastPos = pivotTrans.position;
lastColors = colors;
// 새로 지정된 정점 색상 값을 매쉬에 적용한다.
meshFilter.sharedMesh.SetColors(colors);
위와 같은 코드를 통해 트레일 렌더러가 지난 영역의 모션벡터 값을 담는 매쉬를 만들어 냅니다.
풀 소스는 아래와 같습니다.
using System.Collections.Generic;
using UnityEngine;
[ExecuteAlways]
[RequireComponent(typeof(TrailRenderer))]
public class TrailWithBlurController : MonoBehaviour
{
[SerializeField]
private bool isInit = false;
public MeshFilter meshFilter;
public Transform pivotTrans;
public AnimationCurve mixCurve;
public bool invertAxis = false;
private TrailRenderer _trailRenderer;
private Vector3 lastPos;
private int lastVertexCount;
private Vector3 dir;
private Vector3[] vertices;
private List lastColors = new List();
private void OnEnable()
{
if (meshFilter == null) return;
if (pivotTrans == null) return;
isInit = true;
lastColors = new List();
_trailRenderer = GetComponent();
meshFilter.sharedMesh = new Mesh();
lastPos = pivotTrans.position;
lastVertexCount = meshFilter.sharedMesh.vertexCount;
meshFilter.sharedMesh.GetColors(lastColors);
}
private void OnDisable()
{
lastColors = null;
}
// Update is called once per frame
void LateUpdate()
{
if (!isInit) return;
_trailRenderer.BakeMesh(meshFilter.sharedMesh);
var colors = new List();
meshFilter.sharedMesh.GetColors(colors);
dir = (pivotTrans.position - lastPos).normalized;
if (invertAxis)
{
var tmp = dir.y;
dir.y = dir.x;
dir.x = tmp;
}
dir += Vector3.one;
vertices = meshFilter.sharedMesh.vertices;
var deltaCount = vertices.Length - lastVertexCount;
if (deltaCount > 0)
{
if (lastColors.Count == 0) lastColors = colors;
for (var i = colors.Count - 1; i > 0; i--)
{
if (i - (deltaCount) < 0) break;
colors[i] = lastColors[i - (deltaCount)];
}
for (var i = 0; i < deltaCount; i++)
{
var ratio = (float)i / vertices.Length;
var multiplier = mixCurve.Evaluate(ratio);
var color = new Color(.5f * dir.x, .5f * dir.y, 1f, 1f);
color = Color.Lerp(colors[i], color, multiplier);
colors[i] = color;
}
}
else
{
for (var i = 0; i < colors.Count; i++)
{
colors[i] = lastColors[i];
}
}
lastVertexCount = meshFilter.sharedMesh.vertexCount;
lastPos = pivotTrans.position;
lastColors = colors;
meshFilter.sharedMesh.SetColors(colors);
}
}
(다음 포스트 : [Image Effect] 유니티 블러(Blur) 이미지 효과- 03 Image Effect 적용 (tistory.com))
'개발 > Shader' 카테고리의 다른 글
[Unity/URP] URP에서 Built-in Function이나 Variable에 접근하기 (0) | 2021.06.13 |
---|---|
[Image Effect] 유니티 블러(Blur) 이미지 효과- 03 Image Effect 적용 (1) | 2021.01.04 |
[Image Effect] 유니티 블러(Blur) 이미지 효과- 01 기본 셰이더 (0) | 2021.01.03 |
[Snow Footprint] 04.프로젝트 분석 (完) (0) | 2017.12.25 |
[Snow Footprint] 03.Wave Deformer에 Tessellation 적용 (0) | 2017.12.21 |
소중한 공감 감사합니다