Notice
Recent Posts
Recent Comments
Link
«   2026/02   »
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
Tags
more
Archives
Today
Total
관리 메뉴

MOONSUN

[그래픽스] Toon Shading의 OutLine 표현 : 실루엣 Pass 본문

D3D

[그래픽스] Toon Shading의 OutLine 표현 : 실루엣 Pass

MoonSun_v 2025. 11. 11. 00:26

 

앞 글에서는 Toon Shading에 대해 알아보았는데,

이번에는 Toon Shading과 함께 사용되는 외곽선 실루엣 표현 기법에 대해 알아보도록 하겠다.

 

 

0. 외곽선(Outline) Pass란?

만화풍 렌더링에서 오브젝트의 윤곽을 둘러 강조해주는 역할을 해준다.

 

이 외곽선은 후처리(Post-Process) 로도 만들 수 있지만,

이번에는 모델 자체를 이용한 기하학적(Geometry-based) 외곽선 표현 방법을 알아보도록 하겠다.

 

 

0-1. 외곽선 Pass의 기본 개념

모델의 뒷면(back face)법선 방향으로 살짝 확장하여 렌더링한 후, 그 바깥쪽을 칠한다. 

 

과정을 단계별로 살펴보면서 알아보자.

 

 

 

1. Outline 생성 원리

 

1-1. 법선 방향으로 확장

모델의 각 정점(Vertex)을 법선 벡터 방향으로 살짝 밀어내, 조금 더 큰 형태의 모델을 만든다. 

expandedPos = Input.Position + float4(N * OutlineThickness, 0.0);

 

  • N : 정점의 법선 벡터 (Normal)
  • OutlineThickness : 외곽선 두께 조절 값

 

이렇게 하면 모델 전체가 법선 방향으로 확장되어 살짝 커진다.

 

 

1-2. 뒷면(Back Face)만 렌더링

확장된 모델은 원래 모델보다 약간 커졌기 때문에 겉으로는 뒷면(back face) 만 보이게 된다.

  • 그래서 이 Pass에서는 앞면(front face) 을 제거하고 뒷면만 렌더링 해야 한다.
CullMode = CULL_CW;   // 시계 방향(CW) 면 제거 → 뒷면만 남김

 

 

(참고)

RenderMonkey 기준에서는 CW가 앞면(Front Face) 으로 인식되므로,
이 설정은 “앞면 제거 → 뒷면만 렌더링”을 의미한다.

( DirectX 기본 규칙에서는 반시계(CCW)가 앞면이므로 환경에 따라 설정이 달라진다 아래 설명 추가 )

 

 

 

1-3. 단색으로 색칠

렌더링된 뒷면은 윤곽선처럼 보이게 단색으로 칠한다.

Output.Color = OutlineColor;   // 예: float4(0, 0, 0, 1)

 

이렇게 하면 모델의 원래 표면보다 살짝 바깥쪽에 검은 실루엣이 둘러진 것처럼 보이게 된다. 

 

 

 

2. Pass 구성 예시

Toon 렌더링에서는 보통 두 개의 Pass 로 외곽선을 처리한다.

Pass 설명 Cull Mode 역할
Pass 0 (Outline Pass) 모델의 뒷면을 확장하여 단색으로 렌더링 CULL_CW 외곽선 생성
Pass 1 (Toon 본체) 원래 모델을 Toon Shading 방식으로 렌더링 CULL_CCW 본체 색상 표현

 

이 두 Pass를 순서대로 겹쳐서 그리면 윤곽선 둘러진 만화풍 Toon 모델이 완성 되는 것.

 

 

 

3.  Cull Mode 주의사항

렌더링 엔진마다 “어느 면이 앞면(Front Face)” 인지는 다를 수 있기 때문에,

환경에 따라 Cull 설정을 맞춰줘야 한다.

환경 앞면 정의 Outline Pass Cull Toon Pass Cull
DirectX / HLSL (일반) CCW (반시계 방향) CULL_CCW CULL_CW
RenderMonkey (ATI 파이프라인) CW (시계 방향) CULL_CW CULL_CCW

 

즉, 환경마다 반대가 될 수 있으므로, 렌더링 결과가 뒤집히면 Cull 설정을 바꿔보면 된다.

 

 

 

 

 

4. Toon Rendering + OutLine 전체 렌더링 과정 요약 

 

Pass 0 (Outline)

  • 각 정점을 법선 방향으로 확장
  • 앞면 제거 (Cull CW)
  • 단색으로 뒷면 렌더링 → 윤곽선 생성

Pass 1 (Toon Shading)

  • 원래 모델에 Toon 셰이딩 적용
  • 뒷면 제거 (Cull CCW)
  • 본체 렌더링

 

 

5. Toon Rendering + OutLine 구현 결과 

void TestApp::Render()
{
	m_D3DDevice.BeginFrame(clearColor); // 화면 초기화

	// 상수 버퍼 업데이트 등... 

	...

	// [ PASS 0 : 외곽선 ]
	{
		context->RSSetState(m_pRS_CullFront.Get()); // 앞면 제거 -> 뒷면만 렌더링
		context->VSSetShader(m_pOutlineVS.Get(), nullptr, 0);
		context->PSSetShader(m_pOutlinePS.Get(), nullptr, 0);

		// 외곽선 버퍼 업데이트
		OutlineBuffer outline{};
		outline.OutlineThickness = 1.0f;               // 외곽선 두께
		outline.OutlineColor = XMFLOAT4(1, 1, 1, 1);   // 외곽선 색상 (흰색)
		context->UpdateSubresource(m_pOutlineBuffer.Get(), 0, nullptr, &outline, 0, 0);
		context->VSSetConstantBuffers(3, 1, m_pOutlineBuffer.GetAddressOf());

		// 메쉬 렌더
		boxHuman.Render(context, m_pSamplerLinear.Get());
	}

	// [ PASS 1 : Toon 본체 ]
	{
		context->RSSetState(m_pRS_CullBack.Get()); // 뒷면 제거 (기본)
		context->VSSetShader(m_pVertexShader.Get(), nullptr, 0);
		context->PSSetShader(m_pPixelShader.Get(), nullptr, 0);

		boxHuman.Render(context, m_pSamplerLinear.Get());
	}

	m_D3DDevice.EndFrame(); 
}