알파 블랜딩이랑 버택스(or인덱스)로 만든 하나의 이상의 페이스(플랜등..)에 입힌 텍스쳐에 특정 부분을 투명하게 하기 위한 기능이다.
하지만 알파 블랜딩을 사용할 때 주의점이 존재 하는데,
알파블랜딩을 사용할 때 주는 옵션중에, D3DRS_SRCBLEND, D3DRS_DESTBLEND가 있다.
각각 디폴트 값은, D3DBLEND_ONE, D3DBLEND_ZERO 인데,
사용할 예제에서는
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
처럼 설정해 주었다.
(추가적인 각 추가적인 각 열거체에 대한 설명은 DX도움말 참조)
저 부분을 셋팅하는 이유는,
이미 뿌려져 있는 텍스쳐와 새로 뿌리는 텍스쳐에 대해서 알파 블랜딩 연산을 위해 사용된다.
일단 2개의 텍스쳐(알파값이 존재하는)를 사용해서 어느정도 겹치게 하여 출력해 보자.
단, 여기서 Front는 Z값이 0.3, Back은 Z값이 0.5 정도로 생각하자.
(즉, Back이 조금더 뒤에 있다고 생각하면 될듯)
먼저, Back를 랜더 후
Front를 랜더링해 보자.

우리가 원하는 정상적인 값이 나왔다.
하지만,
Front를 랜더링 한 후 Back를 랜더링 하게 되면,
원치 않는 결과가 나온다는 것을 알 수 있다.

예상하기론, Back가 더 뒤에 있기 때문에 당연히 Front가 먼저 나와야 하는것은 맞지만,
Front가 알파값이 존재 함에도 불구하고 Back이미지를 가리는 현상을 확인 할 수 있다.
그렇다면 무엇이 문제인가..?
결론만 말하자면, 알파블랜딩을 사용하여 텍스쳐를 출력할 때 기존에 뿌려진 이미지에 대해서 새로 이미지를 뿌리면 기존의 이미지와 Z버퍼, 알파값을 잘 조합하여, 화면에 출력하게 되는데,
Back가 먼저 뿌려졌을 땐 뿌려진 Back이미지에 대해서 Front가 더 낮은 Z버퍼값으로 화면에 출력되면서, 알파값이 존재하는 부분에 대해서,
뒤에 존재하는 Back에 대해서 투명하게 처리를 한다는 것이다.
하지만 Front가 먼저 랜더링 되게 되면, Back가 가려지는 이유는,
알파 블랜딩을 사용하면, Front이미지에 알파값이 존재할 지라도, 그 부분에 대해서도 Z버퍼에 기입을 하게 된다는 것이다.
즉, Front가 뿌려지는 순간 그 부분은 이미 Z버퍼가 0.3으로 변환이 되기 때문에,
아무리 Back이미지를 뿌릴려고 하더라도, Z버퍼의 값이 더 높은 Back이미지는 알파연산이 들어가기도 전에 이미 랜더링 대상에서 제외가 된다는 것이다.
그렇다면 여기서 생각해 볼 수 있는 해결책은,
"그렇다면 무조건 Back이미지를 먼저 랜더링 하게 되면 문제가 없는것 아닌가?"
하는 생각이 들 수 있다.
하지만 추후(파티클이나, 다수의 택스쳐 이미지 사용)에 많은 이미지들을 뿌릴때 모든것을 순서를 생각하면서 랜더링 한다는게,
얼마나 큰 과소비인지를 확인 할 수 있게 된다.
그렇기 때문에, 필요한 부분이 알파테스팅이다.
알파테스팅에 대한 결론부터 내리자면,
알파값에 대해서 Z버퍼에 기입을 하지 않는 다는 것이다.
색상은 Z버퍼에 기입을 하기 때문에 자신보다 뒤에 있는 이미지는 당연히 가려질 것이고.
알파값이 적용된 부분은 Z버퍼에 기입을 하지 않았기 때문에 자신보다 뒤에 있는 이미지라고 할지라도 랜더대상에 포함이 된다는 것이다.
사용은 다음과 같다.
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
m_pd3dDevice->SetRenderState(D3DRS_ALPHAREF, 0x00000088);
m_pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
각각에 파라미터에 대한 설명을 하자면,
D3DRS_ALPHATESTENABLE의 디폴트 값은 FALSE로써, 단순히 TRUE를 사용해 사용여부를 확인한다.
D3DRS_ALPHAREF와 0x00000088는 알파테스팅중 사용하게 될 알파값의 수치이다.
이미지가 가지고 있는 알파값과 2번째 파라미터에 대해서 연산을 통해 Z버퍼에 기입을 할건지, 말건지(or 랜더링 할지 말지)를 선택하게 된다는 것이다.
마지막으로
D3DRS_ALPHAFUNC는 D3DCMP_GREATER를 사용해 이미지의 알파값이 ALPHAREF의 2번째 파라미터와 계산했을때, 더 큰지, 작은지, 같은지, 또는 같지 않은지 등에 대해 검사를 하게 되는 것이다.
추가로 D3DRS_ALPHAREF의 디폴트 값은 0
D3DRS_ALPHAFUNC의 디폴트 값은 FALSE이다.
이제 알파테스팅을 사용하고,
Front를 먼저 출력해 주어도.
우리가 원하는 결과가 나오는 것을 확인 할 수 있다.

그렇게 따지면 알파테스팅만 쓰지, 알파 블랜딩은 왜 쓰느냐?
라고 생각할 지도 모르겠지만, 알파 테스팅은 치명적인 결점이 있다.
바로 그것은 이미지의 알파값에 대해서 연산후, 그 연산이 참이냐, 거짓이냐에 따라,
무조건, 투명 or 불투명으로 단정지어지게 된다는 것이다.
즉, 자연스러운 알파값의 변환이 불가능하다고 보면된다.
이미지 마다, 낮은 알파, 높은 알파값등을 사용해 자연스러운 효과를 내고 싶어도 그럴 수 없다는 것이다.
오로지 검사를 통해 투명, 불투명으로만 나뉘게 되기 때문에,
어떤 상황에 적절하게 사용할지는 역시 프로그래머에게 달려 있는 듯 하다.
'프로그래밍 > DirectX' 카테고리의 다른 글
DirectX - 행렬(Matrices) (0) | 2010.06.14 |
---|---|
DirectX-정점(vertex_삼각형 띄우기) (0) | 2010.05.19 |
DirectX-전체 화면 하는 방법 (0) | 2010.05.19 |
DirectX-디바이스 생성 (0) | 2010.05.17 |