오다기리 박의 알고리즘 노트

[셰이더 프로그래밍 입문] 12. 외곽선 찾기와 양각효과 본문

컴퓨터 그래픽스/쉐이더

[셰이더 프로그래밍 입문] 12. 외곽선 찾기와 양각효과

오다기리 박 2018. 7. 1. 23:47

12. 외곽선 찾기와 양각효과

  • sqrt() : 제곱근 구하기

  • 명암이 확 바뀌는 곳이 외곽선이다.

  • 주변의 픽셀이 가지는 값과 현재 픽셀의 값이 어느 정도 이상 차이가 나므로 이 픽셀 값들을 가지고 기본적인 연산을 한 뒤, 그 결과에 따라 외곽선인지 아닌지를 판단한다.

  • 컨벌루션 : 현재 픽셀을 중심으로 해서 그 주위에 있는 픽셀마다 가중치를 곱한 뒤, 그 결과를 모두 더한 값으로 현재 픽셀의 값을 변경하는 연산.

  • 외곽선 찾기에 사용하는 커널 : 소벨 연산자


▶렌더몽키 코드 

- 버텍스 셰이더(외곽선 검출)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct VS_INPUT 
{
   float4 mPosition: POSITION;
   float2 mUV : TEXCOORD0;
};
 
 
struct VS_OUTPUT 
{
   float4 mPosition: POSITION;
   float2 mUV : TEXCOORD0;
};
 
 
VS_OUTPUT vs_main( VS_INPUT Input )
{
   VS_OUTPUT Output;
   
   Output.mPosition = Input.mPosition;
   Output.mUV = Input.mUV;
   
   return Output;
}
cs

- 픽셀 셰이더(외곽선 검출)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
struct PS_INPUT 
{
   float2 mUV : TEXCOORD0;
};
 
sampler2D SceneSampler;
 
float3x3 Kx = { -101,
                -202,
                -101};
 
float3x3 Ky = { 1,  2,  1,
                0,  0,  0,
               -1-2-1};   
 
float2 gPixelOffset;
      
float4 ps_main( PS_INPUT Input ) : COLOR
{
   float Lx = 0;
   float Ly = 0;
   
   for ( int y = -1; y <= 1++y )
   {
      for (int x = -1; x <=1 ; ++x )
      {
         float2 offset = float2(x,y) * gPixelOffset;
         float3 tex = tex2D(SceneSampler, Input.mUV+offset).rgb;
         float luminance = dot(tex, float3(0.30.590.11));
         
         Lx += luminance * Kx[y+1][x+1];
         Ly += luminance * Ky[y+1][x+1];
      }
   }
   
   float L = sqrt((Lx*Lx) + (Ly*Ly));
   return float4(L.xxx, 1);
   
}
cs

- 버텍스 셰이더(양각효과)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct VS_INPUT 
{
   float4 mPosition: POSITION;
   float2 mUV : TEXCOORD0;
};
 
 
struct VS_OUTPUT 
{
   float4 mPosition: POSITION;
   float2 mUV : TEXCOORD0;
};
 
 
VS_OUTPUT vs_main( VS_INPUT Input )
{
   VS_OUTPUT Output;
   
   Output.mPosition = Input.mPosition;
   Output.mUV = Input.mUV;
   
   return Output;
}
cs

- 픽셀 셰이더(양각효과)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
struct PS_INPUT 
{
   float2 mUV : TEXCOORD0;
};
 
sampler2D SceneSampler;
 
float3x3 K =  { -2-1,  0,
                -1,  0,  1,
                 0,  1,  2};
 
float2 gPixelOffset;
      
float4 ps_main( PS_INPUT Input ) : COLOR
{
   float res = 0;   
   for ( int y = -1; y <= 1++y )
   {
      for (int x = -1; x <=1 ; ++x )
      {
         float2 offset = float2(x,y) * gPixelOffset;
         float3 tex = tex2D(SceneSampler, Input.mUV+offset).rgb;
         float luminance = dot(tex, float3(0.30.590.11));
         
         res += luminance * K[y+1][x+1];
      }
   }
   
   res += 0.5f;
 
   return float4(res.xxx, 1);
}
cs

- 결과

외곽선 찾기 / 양각효과 입니다. 배경과 물체의 색이나 명암이 다르면 물체의 외곽선을 볼 수있게 한 결과입니다. 현재 픽셀을 중심으로 해서 그 주위에 있는 픽셀마다 가중치를 곱한 뒤, 그 결과를 모두 더한 값으로 현재 픽셀의 값을 변경하는 컨벌루션 연산을 이용합니다.

img

img