Game Develop

[DirectX11] PixelPicking 구현 본문

ComputerGraphics/DirectX

[DirectX11] PixelPicking 구현

MaxLevel 2021. 10. 8. 20:54

기존의 사용하던 피킹은 반직선피킹인데 프레임이 너무 안나와서 다른 피킹방법이 있나 찾게되었다.

물론 반직선피킹을 하더라도 최적화를 좀 더 하면 프레임이 좀 더 나오긴 하겠지만, 터레인에디터에서는 진짜 말 그대로

피킹지점의 월드좌표만 알아내면 되기 때문에 픽셀피킹을 시도해보았다. 

 

깊이값 샘플링과 행렬계산은 컴퓨트셰이더에서 수행하고 수행결과값(월드값)만 CPU로 리턴시켜서 써먹었다.

깊이값샘플링을 위한 깊이맵은 PreRendr를 해서 따왔다. 렌더타겟을 OM에 셋팅해놓고 터레인 버텍스만 넘겨서 파이프라인 한번 돌린다음 얻어온 렌더타겟의 SRV를 컴퓨트셰이더에 샘플링을 위해 넘겼다.

그냥 같이 바인딩된 DSV의 깊이맵텍스쳐를 바로 컴퓨트셰이더에 넘겨주면 되긴 하는데, 그냥 깊이맵을 시각화하고싶어서 따로 렌더했다.

 

그이후엔 마우스좌표를 -1~1로 정규화시키고 샘플링한 Z값을 z로, w는 1로 설정한 클립공간의 벡터를 생성 후, 투영역행렬과 뷰역행렬을 곱해주면 되는데 뷰역행렬을 곱하기전에 한번 자기자신의 w로 다 나눠줘야한다. 

렌더링파이프라인에선 레스터라이즈스테이트에서 원근나누기를 시행하기때문에, 그 값을 복구하기위해 inverse W값을 곱해줘야 한다고한다. (이부분은 수학적으로는 100% 이해가 잘 안되는부분이긴 하다..)

 

어쨋든 위 과정을 거치면 마우스좌표의 픽셀의 월드값을 구할 수 있다.

 

사실 이렇게만 보면 정말 별거없어보일수도있긴한데, 처음이다보니 깊이맵을 따오는거부터해서 샘플링하는것들도 삽질 많이했다...

일단 이해가 됐든 안됐든 질러봐야하는데, 성격상 도저히 안된다. 덕분에 시간 많이 날렸다.

중간중간 포기하려했는데 도저히 그동안 날린게 아까워서 계속 시도했는데 결국 성공해서 진짜 뿌듯하다.

 

프레임마다 돌린다고 했을 시, 기존의 반직선피킹은 40프레임?정도에서 왔다갔다거렸는데 픽셀피킹은 140프레임넘게나온다. 반직선피킹은 일단 컴퓨트셰이더에 터레인의 폴리곤을 다넘기기도 해야하고 컴퓨트셰이더에서 체크한 충돌된 폴리곤들에 대해 한번더 가까운 폴리곤을 탐색해야하니... 당연히 프레임이 안좋을수밖에없다. 

그리고 터레인의 폴리곤들을 검사하다보니 터레인이커질수록 프레임은 더 떨어질수밖에없다. 하지만 픽셀피킹은 그런거에 구애받지않기때문에 아주 좋다.