Featured image of post 셰이더 프로그래밍 기초공부 18 _ 블러 효과 기본

셰이더 프로그래밍 기초공부 18 _ 블러 효과 기본

블러 효과의 기본.
박스 샘플링 기법이 아닌, 가우스 함수 기법을 흉내내어 작성한다.

블러는, 기본적으로 주위의 색이 자신의 픽셀에 영향을 끼친다는 원리로 제작된다.
즉 셈플러에서 텍스쳐를 7개를 받아 온다고 치면,
가운데의 자기 색깔을 제외하고 좌우 3픽셀씩에서 각각 색상값을 더 얻어와서
자기 위치에다가 더해버리는 방식으로 제작되는 것이다.

물론 멀리 있을수록 가중치는 엷기 때문에 엷게 더해진다.

그렇게 해서 y축 (세로) 로만 블러 효과를 낸 예제는 다음과 같다.
(세로 가로 다 낼 수도 있지만 그러면 7*7= 49 개의 매트릭스 계산을 해야 하기 때문에, 2패스(7+7 =14)를 사용한다)

1pass의 핵심공식은 이거다.
color += tex2D(Texture0,float2(In.TexCoord.x+gaussFilter[i].x * texScaler,
                                  In.TexCoord.y+gaussFilter[i].y * texScaler))
                                  *gaussFilter[i].w;

원본 이미지는 다음과 같음.
그걸 y축 블러 효과로 만들었다.
설명 쓰다가 마지막에서 4배 뻥튀기 데이터를 발견.
뭐하는 짓이야.
어쩐지 너무 하얗게 날라간다 했어.

뻥튀기를 없애면 이렇게 나온다.
오 이제 좀 블러같다.좀 약해 보이기는 하는데.. 그래서 넣었구나.

//버텍스 쉐이더 부
struct VS_OUTPUT
{
   float4 pos       : POSITION0;
   float2 texCoord  : TEXCOORD0;
};

VS_OUTPUT vs_main( float4 inPos: POSITION )
{

   VS_OUTPUT o = (VS_OUTPUT) 0;

//포지션을 mul로 메트릭스와 곱하는 것 처럼 sign으로 변환했다. 
   inPos.xy = sign( inPos.xy);
//그리고나서 출력은, z값을 0으로, a값은 1로 해서 합쳤다. 아마도 2D니까 z값은 0인거 같은데,
//xy를 왜 sign으로 해야 하는지는 잘 모르겠다. 아시는분 ?
   o.pos = float4( inPos.xy, 0.0f, 1.0f);

   // get into range [0,1] 입력범위를 0과 1 사이에 넣는단다.
 //으음. 한눈엔 잘 모르겠다. 텍스쳐 코디네이트를 받지 않고, 포지션에서만 받는다라…
// 0에서 1이면 처음부터 끝까지겠지. 아…. 이건 설마 양수로 만들기 위한 것? 
//이건 물어봐야겠다.
   o.texCoord = (float2(o.pos.x, -o.pos.y) + 1.0f)/2.0f;
   return o;
}

//픽셀 쉐이더 부

//쌈빡하게 샘플러 정의해 주시고.
sampler2D Texture0;

//float4 짜리 7줄의 행열 만들어 주신다.
//현재 Y의 값이 -3부터 +3까지 변하고,
//각 행열당 가중치가 나와 있다.

float4 gaussFilter[7] =
{
   0.0,-3.0,0.0,  1.0/64.0,
   0.0,-2.0,0.0,  6.0/64.0,
   0.0,-1.0,0.0, 15.0/64.0,
   0.0, 0.0,0.0, 20.0/64.0,
   0.0, 1.0,0.0, 15.0/64.0,
   0.0, 2.0,0.0,  6.0/64.0,
   0.0, 3.0,0.0,  1.0/64.0
};

//텍스쳐가 128픽셀인가부다. 비율로 나타내 주기 위해 이렇게 쓴다.
float texScaler = 1.0/128.0;
//없어도 상관없을듯. 에니메이션 시킬때라던가 그럴땔 위해서 있는 듯
float texOffset = 0.0;

struct PS_INPUT
{
   float2 TexCoord : TEXCOORD0;
};

struct PS_OUTPUT
{
   float4 Color : COLOR;
};

PS_OUTPUT ps_main (PS_INPUT In)
{
   PS_OUTPUT Out;
  
   float4 color = 0.0;
   

//앗싸 for문이다. 행열과 같게 7번 돌린다.
   int i;
   for (i=0;i<7;i++)
  
   {
   //그리고는 한 픽셀에 값을 누적시킨다.
 //텍스 스케일러가 각 픽셀 위치값을 이동시키고, w 데이터가 가중치를 결정해 주는 것을 볼 수 있다.
   color += tex2D(Texture0,float2(In.TexCoord.x+gaussFilter[i].x * texScaler+texOffset,
                                  In.TexCoord.y+gaussFilter[i].y * texScaler+texOffset))
                                  *gaussFilter[i].w;
   }  

//걍 4배 뻥튀기?!?                                  
Out.Color = color * 4.0;

return Out;
}

Hugo로 만듦
JimmyStack 테마 사용 중