3D그래픽스의 개념과 렌더링파이프라인 (5/5)

Unity3D 2014. 4. 16. 11:06
반응형


http://allosha.tistory.com/


2008-04-18 12:00:00
図1: GPU内部におけるレンダリングの流れ レンダリング最終工程~レンダーバックエンド ピクセルシェーダの出力は、ずばりいえば「ポリゴンを構成するその画素が、そのシーンではその色に決定されました」ということ ...... >> Read more

(C) Mainichi Communications Inc. All rights reserved.



                                   그림1: GPU 내부에서의 렌더링 흐름

렌더링 최종공정~ 렌더 백엔드

픽셀셰이더의 출력은, 정확히 말하면 「 폴리곤을 구성하는 그 화소가, 그 장면에서는 그 색으로 결정되었습니다. 」라는 것이고, 그대로 비디오 메모리에 써 넣어서 「 한 픽셀의 그리기 완료 」라고 하고 싶지만, 아직 할 일이 있다.

그것이 [10]의 렌더 백엔드 (Render Backend)이다. 덧붙이면 NVIDIA의 경우는 이 부분을 ROP유닛이라고 부르기도 한다. ROP유닛은 Rendering Output Pipeline, 또는 Raster Operation의 약어라는 설이 있지만 확실치는 않다. 본 연재에서는 전자를 정확한 해석이라고 해 두자. 

어쨋든, 여기에서는 픽셀셰이더의 출력을 「 써넣어도 좋은것인가의 검증 」, 써 넣을 때는 「 어떻게 써넣을까의 결정 」등의, 비디오 메모리의 쓰기 제어 부분이다. 픽셀셰이더 자신은 텍스처를 읽어 낼 수는 있어도, 비디오 메모리에 써낼 수는 없기 때문에 이 처리는 지극히 중요한 부분이다.
 
그런데, 다이렉트X 9 / SM 2.0 세대 이전의 GPU에서는 픽셀셰이더의 개수와 ROP유닛의 개수가 항상 일치했었기 때문에, 픽셀셰이더와 ROP유닛은 "대(對)" 와 같은 관계를 상상할 수 있었다. 하지만, 다이렉트X 9 / SM 3.0 세대 이후의 GPU에서는 픽셀셰이더 프로그램의 고도화와 함께 픽셀셰이더 개수의 증강이 중점적으로 이루어진 결과, ROP유닛의 개수는 픽셀셰이더의 개수 보다도 적은 것이 일반화 되었다. 

최근 GPU에서는 픽셀셰이더 > ROP유닛 구성이 일반적이다. 
그림은 GeForce 7800 GTX의 블럭다이어그램. 
중간의 4x6 = 24기(基)가 픽셀셰이더. 최하단의 16기(基)가 ROP유닛.

「 써 넣어도 좋은것인가의 검증」으로써는 「 알파테스트 」「 스텐실테스트 」「 깊이테스트 」라는 것이 있다. 

알파테스트는 출력하는 픽셀색이 완전히 투명한가 아닌가의 테스트. α성분이 0으로 투명하다면 그릴 필요가 없으므로 그 픽셀은 그리지 않는다.

그림7: 알파테스트 - 불투명한 부분의 픽셀만 그린다.

<그림 설명>
알파테스트의 예
투명 α = 0
불투명 α = Max
이 픽셀의 그리기는 취소된다


스텐실테스트는 다목적 연산 프레임 버퍼로 이용되는 스텐실버퍼의 내용에 따라서, 어플리케이션이 설정한 조건을 통과할 수 없으면 그 픽셀은 그리지 않는다. 화면의 일부를 도려낸다든지, 스텐실쉐도우볼륨 기법의 그림자 생성 시 그림자 형태를 뽑는 처리등에 응용된다.

그림8: 스텐실테스트 - 스텐실버퍼의 내용을 참조해서, 미리 설정한 테스트 조건을 만족하면 그린다. 이 그림은 「 스텐실버퍼의 내용이 A의 부분만을 씬에 그린다」는 예시이다.

<그림 설명>
(제목) 스텐실테스트의 예
좌 상: 렌더링하는 씬
좌 하: 스텐실 버퍼
우: A 부분은 스텐실테스트를 통과했으므로 그리고, B 부분은 통과되지 않아 취소한다

깊이테스트는 지금부터 그릴 픽셀이 시점에서 봤을 때 가장 앞에 있어서 잘 보이는 픽셀인지 아닌지를 검사하는 것이다. 그리는 픽셀과 1 대 1로 대응하는 Z버퍼라고 불리는 깊이값(Z값)을 넣어두는 버퍼를 미리 준비해 여기서 읽어 낸 깊이값과 지금부터 그릴려는 픽셀의 깊이값을 비교하는 것이 「깊이테스트의 실제 형태」이다. 깊이값은 픽셀셰이더에 의해서 계산되어 나온다.

또한, 반투명 3D 오브젝트를 구성하는 반투명 픽셀을 그리는 경우등은 이 깊이테스트 자체를 하지 않는 경우도 있다.

그림9a: 깊이테스트 - 순서 없이 그릴 때, 깊이테스트는 중요해 진다.

그림9b: Z버퍼에 깊이값을 써넣은 흔적이 없는 곳에는 무조건 써 넣는다. 써넣은 흔적이 있는 곳에서는 깊이테스트를 해서 지금부터 그려내려는 픽셀이 앞이라고 판단할 수 있는 경우만 그린다.

<그림 설명>
그림9a:
상:
(원) 시점
(버블) 본래는 이렇게 보일 것이다
안쪽(깊이값 = 15)
중간(깊이값 = 10)
앞쪽(깊이값 = 3)
하:
고양이 -> 얼굴-> 개 순서로 그렸다고 하면
아무 생각없이 고양이->얼굴->개 이렇게 그리면, 나중에 그린 개가 가장 앞에 그려져 버린다.
이러면 않된다.
그림9b:
프레임버퍼, z 버퍼
상:
중:
A: 여기는 깊이값이 15인 값이 그려진 흔적이 있다. old 15 > new 10 으로 지금부터 그릴 것이 앞이라고 판단. 깊이테스트를 통과하므로 그린다.
B: 여기는 이미 깊이값 3인 값이 그려진 흔적이 있기 때문에 old 3 < new 10으로 앞에 무언가가 있다고 판단.
깊이테스트를 통과하지 못하므로 그리지 않는다.
C: 그려진곳은 Z버퍼를 업데이트해서 다음 깊이테스트에 대비한다.


「 어떻게 써넣을까의 결정」에 대한 변형(variation)으로는 「 α합성(α블렌딩) 」, 「 포그(안개) 」등이 있다.

α합성은 단지 픽셀을 덮어쓰기해서 그려넣는 것이 아니라, 이미 써넣어진 픽셀색과 반투명합성 계산을 해서 다시 쓰는 처리를 하는 것이다. 렌더링 대상의 프레임버퍼로 부터 픽셀색을 읽어 낸다... 즉 비디오메모리 읽기가 들어가고, 거기에  α합성계산까지도 할 필요가 있기 때문에 의외로 부하가 큰 처리이다. 여담이지만, 3D벤치마크  소프트웨어등에서 반투명 폴리곤 겹쳐쓰기를 연속적으로 한다거나 하는 것은 이 성능을 평가하려는 목적이 있기 때문이다.

그림11: α합성 - α합성에서는 이미 렌더링한 결과를 읽어내 거기에 합성계산을 해서 그려내는 것이기 때문에 부하가 크다.

<그림 설명>
(제목) α합성
(좌) ~ (우)
지금부터 그려 낼 내용 + (프레임버퍼이미 그려져 있는 내용 합성상태를 나타내는 α값에 따라서 합성

안개(fog)는 지금부터 그릴 픽셀의 깊이값에 따라서 미리 설정해 둔 포그컬러의 섞는상태를 조정하는 처리를 하는 것이다. 안으로 깊이 들어가면 갈수록 그 포그의 픽셀색을 흰색에 가깝게 하는 것과 같은 설정을 하면, 안쪽이 뿌옇게 보이는 공기원근(空氣遠近)의 표현이 가능하다. 

그림12: 안개 - 안으로 들어갈수록  픽셀값을 뿌옇게 함으로써 공기의 원근 표현이 가능하다.



물론, α합성도 안개처리도 하지 않는경우는 그 픽셀색을 그대로 비디오메모리에 써내는 처리를 한다. 그리고 써낼때는, 그다음 이후의 다른 픽셀의 깊이테스트에 대비해서, 깊이값을 업데이트해 둔다. 

또한, 격자형 화소배열의 화면화소에서의 픽셀이 톱니같은 느낌(jaggy)을 주는 현상을 감소시키는 안티앨리어싱처리도 이 렌더백엔드 부분에서 이루어진다. 



(トライゼット西川善司)

반응형
: