[DirectX11 3D] Shadow

한창희·2024년 5월 30일

DirecX3D 엔진 만들기

목록 보기
10/14

📌그림자 표현하기

그림자를 찍기 위해서는 물체를 화면에 렌더링할 때, 물체가 Directional Light에게 빛을 받고있는지 여부에 대해서 알아야한다.

그럼 어떻게하면 Light에게 빛을 받고 있는지 알 수 있을까?

위와 같이 물체가 존재한다고 생각해봤을 때, 그림자가 지는 부분은 빛이 들어오지 않는다.
광원의 입장에서 생각해보면 광원은 앞에 존재하는 물체 때문에 그림자가 지는 부분이 보이지 않는다.

그렇다면 물체를 렌더링하기 전에 광원입장에서 화면을 찍어두면 어떨까?

광원의 시점에서 물체들을 렌더링하고, 깊이 값들을 저장해 놓는다면 deferred 랜더링 단계에서 position 텍스쳐를 통해서 해당 물체를 광원 입장에서 바라 보았을 때, 어떤 깊이가 저장되어있는지 알 수 있다. 해당 깊이와 현재 해당 픽셀에 저장되어 있는 포지션 타겟의 깊이를 비교하여 광원 입장에서 보았을 때, 해당 물체가 보이는지를 판단하여 보이지 않는다면 그림자가 생겼다고 판단할 수 있다.


📌광원 시점에서 물체의 깊이를 저장하기

  1. MRT 만들기
    광원입장에서 물체의 깊이를 저장할 텍스쳐를 만들어 해당 텍스쳐를 렌더 타겟으로 하는 MRT를 만들어 낸다.
  2. 광원 입장에서 물체를 찍기 위해 Light 컴포넌트에 카메라 기능을 할 오브젝트를 추가한다.
  3. 그림자를 그림 물체 분류하기
    매 틱마다 Light에 존재하는 카메라는, 현재 레벨의 모든 오브젝트들을 가져와서 그림자를 그릴물체인지 확인한 후 자신이 가지고 있는 쉐도우 오브젝트들을 담는 벡터에 담아준다.
  4. 모든 물체 분류가 끝난 뒤에, 카메라는 해당 물체를 자신의 View, Projection 행렬을 이용해 ShadowDepthMap에 렌더링한다.

📌라이팅 시점에서 그림자의 여부를 판단하기

  1. 포지션 타겟 텍스쳐를 이용해 해당 픽셀에 존재하는 물체가 어떤 포지션에 존재하는지 알아내기
  2. 포지션 타겟에서 샘플링한 물체의 포지션을 광원의 Projection Space로 이동 하기
    현재 포지션 타겟에 저장된 값은 라이팅을 위해 main 카메라의 view space에 존재하므로 먼저 월드 스페이스로 이동하기 위해 메인카메라의 view 역행렬을 곱한다. 그리고 광원 기준 Projection Space로 이동하기 위해 광원에 달린 카메라의 View Projection 행렬을 곱한다.
  3. Projection Space로 이동한 뒤, ShadowDepthMap를 이용해 해당 픽셀에 저장된 깊이를 가져와 비교하여, 그림자를 판단하여 라이팅한다.
  4. ShadowDepthMap에 저장된 범위를 벗어나는 경우 그림자를 처리하지 않도록 수정한다.

0개의 댓글