1.11 전/후면 컬링
이 섹션에서는 전면과 후면이라는 중요한 렌더링 개념을 살펴봅니다. 파이프라인 디스크립터의 primitive 설정에서 cullMode 필드를 back 또는 none으로 설정한 것을 보셨을 것입니다. 이제 cullMode의 의미와 컬링의 중요성에 대해 논의해 봅시다.
컬링은 관찰자로부터 멀리 떨어져 있어서 현재 보이지 않는 불필요한 지오메트리를 제거하는 과정입니다. 프리미티브 설정에서 cullMode는 특히 면 컬링 모드를 나타냅니다. 이를 none으로 설정하면 모든 삼각형이 유지되고, back으로 설정하면 GPU가 후면 삼각형을 폐기하도록 지시합니다.
컬링은 래스터화 전에 발생합니다. 전면의 정점 순서는 cw(시계 방향) 및 ccw(반시계 방향)와 같은 토폴로지 구성의 frontFace 매개변수로 지정됩니다. GPU는 삼각형 정점의 순서를 검사합니다. 면 방향이 컬링 설정과 일치하면 삼각형은 래스터화되지 않습니다.
컬링과 밀접하게 관련된 또 다른 개념은 클리핑으로, 이 또한 보이지 않는 지오메트리를 제거하고 렌더링 작업 부하를 줄이는 역할을 합니다. 컬링은 면 방향을 다루는 반면, 클리핑은 지오메트리와 시야 절두체(view frustum) 사이의 공간 관계에 중점을 둡니다. 클리핑은 시야 절두체의 경계에 대해 각 삼각형을 검사합니다. 이 뷰 볼륨 밖에 완전히 있는 모든 삼각형은 추가 처리 전에 폐기되거나 "클리핑"됩니다.
컬링이 비활성화된 경우, @builtin(front_facing) 불리언을 사용하여 래스터화된 프래그먼트가 우리를 향하거나 멀어지는 삼각형의 일부인지 확인할 수 있습니다. 이 정보를 사용하면 프래그먼트의 방향에 따라 다른 색상을 할당하여 외부 및 내부 표면을 다르게 렌더링할 수 있습니다. 이러한 개념이 간단해 보일지라도, 이는 다음 장에서 다룰 깊이(Z-버퍼)를 이해하는 데 기초가 됩니다.
전면과 후면을 다르게 시각화하면 깊이 테스트를 비활성화했을 때 발생할 수 있는 아티팩트를 파악하는 데 도움이 됩니다. 셰이더 측 변경 사항을 살펴보겠습니다:
@fragment
fn fs_main(in: VertexOutput, @builtin(front_facing) face: bool) -> @location(0) vec4 {
if (face) {
return vec4(0.0, 0.0, 1.0 ,1.0);
}
else {
return vec4(0.0, 1.0, 0.0 ,1.0);
}
}
JavaScript 코드에서는 파이프라인 디스크립터의 프리미티브 섹션에서 cullMode를 none으로 설정하여 후면 컬링을 비활성화해야 합니다. 이렇게 하면 뒤집힌 면이 프래그먼트 스테이지에 도달합니다:
primitive: {
topology: 'triangle-strip',
frontFace: 'ccw',
cullMode: 'none'
}
렌더링이 부정확하게 나타나고, 다른 면에 의해 가려져야 할 일부 면이 관통하는 것을 볼 수 있습니다. 이는 설정에서 깊이를 활성화하지 않았기 때문에 발생합니다. 깊이 없이 어떤 삼각형이 다른 삼각형을 가려야 하는지 결정할 수 없습니다. 이 상황에서 가림은 오직 그리기 명령의 순서에 의해서만 결정됩니다. 이 문제는 다음 튜토리얼에서 다룰 것입니다.