[Image Effect] 유니티 블러(Blur) 이미지 효과- 01 기본 셰이더
- -
이번 시리즈는 아래와 같은 결과물을 만들기 위해 세 편으로 나뉩니다.
(2편 : [Image Effect] 블러(Blur) 이미지 효과- 02 Trail Renderer 모션벡터 획득 (tistory.com))
(3편 : [Image Effect] 블러(Blur) 이미지 효과- 03 Image Effect 적용 (tistory.com))
첫 편인 기본 셰이더에선, 블러 텍스쳐를 활용해 원본의 특정 영역에 원하는 방향으로 모션블러를 주는 방법을 설명하며
두 번째 편에서는, 이 셰이더를 Trail Renderer에 응용하기 위한 Trail Renderer의 모션 벡터값을 버텍스에 추가하는 방법
세 번재 편에서는, 이 두 가지를 종합해 Trail Renderer가 지나간 영역에 지나갈 당시의 모션 벡터값을 활용해 블러를 주는 방법을 설명합니다.
물론 전 배워가는 학생 이기에 설명하는 과정에서 더 나은 방법이나, 실수가 발생해 지적받아야 하는 부분이 있습니다.
이럴때는, 자비로운 마음으로 댓글에 더 나은 방법이나 실수한 부분을 알려주시면 공부하고 내용을 수정하겠습니다.
제가 알고 있기론, 카메라 효과에 적용하기 위한 블러 기법은 싱글 패스와 멀티 패스, 그리고 또 싱글 패스 안에서 가우시안, 중간값, 최소값 등 여러 공식을 통해 나뉘지만, 이번에 만들 셰이더의 목적은 모션 블러 효과를 텍스쳐를 통해 원하는 위치에 표현하는 것이기 때문에 가장 간단한 평균값 기반의 블러링을 사용했습니다.
이번 포스팅의 완성된 상태는 위 영상과 같습니다.
블러맵에 할당된 텍스쳐의 R 채널의 값은 X축 방향, G 채널 값은 Y축 방향으로 Effect만큼의 효과를 줍니다.
이를 위해 아래와 같은 프로퍼티를 정의합니다.
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_BlurTex ("BlurMap", 2D) = "black" {}
_Sample ("Sample", Range(4, 64)) = 16
_Effect ("Effect", float) = 1
_Threshold ("Threshold", float) = 0.001
}
1. _MainTex는 블러가 들어갈 원본 텍스쳐입니다.
2. _BlurTex는 모션벡터가 텍스쳐화 되어있는 샘플로, Red는 X 변화를, Green은 Y변화를 줍니다.
3. _Sample은 블러 샘플링의 숫자를 의미하며, 숫자가 높을수록 연산량이 많으니 적당히 사용할만큼 4~64정도의 Range를 줬습니다.
4. _Threshold 이하의 블러 효과가 무시됩니다.
Vertex Shader는 크게 사용되지 않기에 바로 Fragment Shader 설명으로 넘어갑니다.
싱글 패스 블러는 기본적으로 반복문을 사용하기에 반복문 밖에 계속해 사용될 변수를 선언했습니다.
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = fixed4(0,0,0,0);
// blurMap에서 추출한 RG값이 담긴다.
float2 mDir = float2(0,0);
// blurMap에서 추출한 B값이 담긴다.
float mIntensity = 0;
float divider = 1/_Sample;
// 반복문을 통해 중첩되는 Blur효과의 값이다.
float4 blurSum = float4(0, 0, 0, 1);
...반복문 영역
return col;
}
위와 같이 선언한 값들은 반복문에서 다음과 같이 사용됩니다.
for(int j = 0; j < _Sample; j++)
{
// 같은 픽셀이 몇 번째 반복됐는지에 따라, 효과가 적용되는 양을 다르게 하기 위해 선언된다.
float scale = j * divider;
// 블러맵에 의해 수정된 좌표계를 얻는다.
float2 cCoord = i.uv + (.5-i.uv) * blurSum.xy * _Effect * scale;
float4 offset = tex2D(_BlurTex, cCoord);
// 방향은 음과 양으로 나뉘어 표현되야 하기에, 중간값인 상수 .4961을 빼줘 방향성을 표현한다.
mDir = offset.rg - .4961;
if(length(mDir) <= _Threshold)
mDir = 0;
else
mDir += .4961;
blurSum.xy += mDir * divider;
mIntensity = offset.b;
mIntensity = pow(mIntensity, 3);
col += tex2D(_MainTex, cCoord) * divider;
}
위와 같은 방법을 모두 적용하면 다음과 같은 풀 소스가 나옵니다.
Shader "Custom/ImageEffect/TextureBasedBlurring"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_BlurTex ("BlurMap", 2D) = "black" {}
_Sample ("Sample", Range(4, 64)) = 16
_Effect ("Effect", float) = 1
_Threshold ("Threshold", float) = 0.001
}
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;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
sampler2D _BlurTex;
float4 _MainTex_ST;
float4 _BlurTex_ST;
float _Sample;
float _Effect;
float _Threshold;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = fixed4(0,0,0,0);
// R = X, G = Y => RG = UV offset
float2 mDir = float2(0,0);
float mIntensity = 0;
float divider = 1/_Sample;
float4 blurSum = float4(0, 0, 0, 1);
blurSum.xy = mDir * divider;
for(int j = 0; j < _Sample; j++)
{
float scale = j * divider;
float2 cCoord = i.uv + (.5-i.uv) * blurSum.xy * _Effect * scale;
float4 offset = tex2D(_BlurTex, cCoord);
mDir = offset.rg - .4961;
if(length(mDir) <= _Threshold)
mDir = 0;
else
mDir += .4961;
blurSum.xy += mDir * divider;
mIntensity = offset.b;
mIntensity = pow(mIntensity, 3);
col += tex2D(_MainTex, cCoord) * divider;
}
return col;
}
ENDCG
}
}
}
(다음 포스트 : [Image Effect] 블러(Blur) 이미지 효과- 02 Trail Renderer 모션벡터 획득 (tistory.com))
'개발 > Shader' 카테고리의 다른 글
[Image Effect] 유니티 블러(Blur) 이미지 효과- 03 Image Effect 적용 (1) | 2021.01.04 |
---|---|
[Image Effect] 유니티 블러(Blur) 이미지 효과- 02 Trail Renderer 모션벡터 획득 (0) | 2021.01.04 |
[Snow Footprint] 04.프로젝트 분석 (完) (0) | 2017.12.25 |
[Snow Footprint] 03.Wave Deformer에 Tessellation 적용 (0) | 2017.12.21 |
[Snow Footprint] 02.Tessellator - 02 (Tessellator and Domain Stage) (0) | 2017.12.16 |
소중한 공감 감사합니다