본문 바로가기
ComputerGraphics/HLSL

쉐이더프로그래밍 / 툰(toon) 쉐이딩

by lucidmaj7 2020. 6. 24.
728x90
반응형

컴퓨터 그래픽스에서 실제와 가까운 렌더링은 궁극적인 목표이지만 때로는 실제와 거리가 있는 미적인 요소를 충족 시켜야 할 때도 있습니다. 이번에 공부해본 툰쉐이딩은 그런 경우의 예라고 볼 수 있습니다.

구현 결과를 먼저 보자면 다음과 같습니다.

마치 만화 효과 같이 색상이 단계적으로 표현되고 있습니다.

난반사 쉐이더에서 보았던 코사인 그래프와 툰쉐이딩 그래프를 비교해 놓은 것입니다. 마치 계단처럼 단계가 나뉩니다.

쉐이더프로그래밍입문

수치적으로 비교를 해보면 아래와 같습니다.

난반사광의 양 툰쉐이더의 양
0 0
0~0.2 0.2
0.2~0.4 0.4
0.4~0.6 0.6

즉 난반사 광에서 무조건 0.2단위로 올림 하면 툰쉐이더 양이 나오게 되는 겁니다.

정점쉐이더

정점 쉐이더는 지난번 람베르트 난반사의 정점 쉐이더와 비슷합니다. 하지만 이번에 다른점은 world view projection 행렬이 미리 곱해져서 입력 되었다는 점인데요. 이렇게 하면 3번 곱할 연산이 1번으로 줄어들게 되어 성능상 이점이 있다고 합니다.

대신에 월드공간으로 계산된 법선 벡터를 구애야합니다. 하지만 월드 행렬은 이미 뷰와 투영행렬이 곱해져서 주어지지 않았습니다. 대신에 굳이 로컬->월드 변환을 하지 않고 월드 공간에 정의된 빛을 로컬공간으로 옮겨와 주면 간단히 해결됩니다. 그러기 위해서는 월드 행렬의 역행렬을 빛의 위치에 곱하여 로컬로 변환해줍니다.

struct VS_INPUT{
   float4 mPostion:POSITION;
   float3 mNormal:NORMAL;
   
};

struct VS_OUTPUT
{
   float4 mPosition : POSITION;
   float3 mDiffuse : TEXCOORD1;
};

float4x4 gWorldViewProjectionMatrix;
float4x4 gInvWorldMatrix;
float4 gWorldLightPosition;

VS_OUTPUT vs_main(VS_INPUT Input)
{
   VS_OUTPUT Output;
   
   Output.mPosition = mul(Input.mPostion, gWorldViewProjectionMatrix);
   
   float3 objLightPosition= mul(gWorldLightPosition, gInvWorldMatrix); //월드공간의 빛의 위치를 로컬로
   float3 lightDir = normalize(Input.mPostion.xyz- objLightPosition);
   
   Output.mDiffuse = dot(-lightDir, normalize(Input.mNormal));
   
   return Output;

}

 

픽셀 쉐이더

float3 gSurfaceColor; //물체 표면 색
struct PS_INPUT
{
 float3 mDiffuse : TEXCOORD1; //디퓨즈 값
};

float4 ps_main(PS_INPUT Input) : COLOR
{
 float3 diffuse = saturate(Input.mDiffuse); //디퓨즈 값

 diffuse = ceil(diffuse * 5) / 5.0f; //반올림

 return float4( gSurfaceColor * diffuse.xyz, 1); //최종 값

}

우리가 원하는 것은 0.2 단위로 디퓨즈 값을 올림 하는 것입니다. 올림연산을 할때에는 HLSL의 ceil을 사용합니다. ceil함수는 무조건 바로위 정수로 올림을 하는 함수입니다. 하지만 디퓨즈 값은 0~1.0이므로 무조건 1로 올림이 될 것입니다.

때문에 Diffuse값에 5를 곱하여 올림연산을 하고 다시 5로 나눠주면 바로 0~1사이의 값이 만들어집니다.

결과

렌더몽키에서 구현한 결과는 다음과 같습니다.

툰쉐이딩.rfx
0.05MB

 

DirextX 11에서 구현

DirectX11에서 구현한 결과는 다음과 같습니다.

 

https://github.com/lucidmaj7/directx11test/tree/shader_toon/MyShaderTest

 

lucidmaj7/directx11test

directx11test. Contribute to lucidmaj7/directx11test development by creating an account on GitHub.

github.com

 

 

728x90
반응형

댓글