2023년 5월 11일 강의
멀티렌더타겟 : 렌더타겟을 여러 장 두는 방식을 적용해볼 것이다.
MRT용 필터를 생성하고, CEntity를 상속받은 CMRT 클래스를 생성한다.
지금까지는 RenderTarget 하나, DepthStenctil 하나를 셋팅해서 OM단계의 마지막에 해당 렌더타겟에 출력을 했었다.
(우리가 알고 있기로는 SwapChain이 렌더타겟을 두개 가지고서 Present 할 때마다 백버퍼 - 프론트버퍼를 바꿔가며 렌더링을 한다는 것이지만, 실제 DX11 코드에서는 스왑체인이 가지고 있는 렌더타겟 수가 2개가 아닌 1개라고 나온다. 추측하건데 렌더타겟 하나를 가지고 사본을 만들어 둘을 번갈아가며 사용하는 것 같다고 한다. DX12에서는 보편적인 개념대로 SwapChain에 2개의 렌더타겟을 세팅해줘야한다고 한다.)
기존 우리 엔진에서 렌더매니저에서 렌더가 시작될 때마다 이 RenderTarget과 DSTex를 지정해주고 (OMSet) 지정된 색상으로 Clear해주고 있었다. 사실은 OMSet의 경우에는 클라이언트 시작할 때 한 번만 해도 됐지만, ImGui를 렌더링 할 때 ImGui 쪽에서 그쪽에서 만들어진 스왑체인의 렌더타겟으로 주도권을 뺏어가기 때문에 매 프레임마다 재지정해준 것이었다.
아무튼 렌더타겟을 여러 장 가질 수 있는 개념의 MRT 방식으로 전환하게 되면, 여러 장의 렌더타겟에 한 번에 출력을 할 수 있게 된다. 단, 렌더타겟의 개수와 상관 없이 깊이 텍스처는 무조건 한 장이다. (애초에 코드에서 렌더타겟은 개수를 인자로 받지만, 깊이 텍스처는 그냥 한 장만 받는다)
DX9 기준 렌더타겟은 최대 4개, DX11은 최대 8장까지 설정할 수 있다.
따라서 미리 최대 크기만큼의 8칸짜리 배열을 만들어둔다. 몇 개의 렌더타겟 텍스처를 사용하는지에 대한 변수도 저장한다. DSTex도 추가한다. (MRT는 클론되지 않으므로 CLONE_DISABLE)
이제 우리 엔진의 렌더타겟을 이 MRT로 교체해볼 것이다.
지금까지는 Device에서 RT, DSTex를 따로 관리했지만, 이제부터는 MRT라는 클래스로 묶어서 관리를 하는 것이다.
RT와 DSTex를 인자로 주면 MRT를 생성해주는 함수를 MRT 클래스 내에 만들어보자.
최대 8칸의 렌더타겟이 들어있는 배열 주소를 주면, 8번만큼 배열을 돌며 렌더타겟을 멤버 배열에 등록한다. null을 만나면 더 이상 렌더타겟이 없다는 의미로, i를 렌더타겟 개수로 저장 후 반복문을 탈출하고, DSTex를 저장한다.
MRT 내의 모든 멤버는 다 Ptr로 관리되고 있으므로 따로 소멸자에서 관리할 필요가 없다.
이렇게 만들어지는 MRT는 여러 타입이 있으며, 이제부터 일괄적으로 렌더매니저에서 관리할 것이다.
define에서 enum으로 MRT의 타입을 정의하고, 렌더매니저의 멤버에 MRT를 추가한다.
지금 만들 MRT는 지금껏 써왔던 가장 기본적인 Swapchain 용 MRT이다.
이제 Device는 더 이상 RT와 DSTex를 직접적으로 알 필요가 없다. (MRT로 묶여, MRT가 각각을 알고 있을테니까). 그리고 렌더 타겟과 관련된 모든 함수(OMSet, Clear) 역시 Device가 아니라 MRT에서 호출해야한다.
-> 따라서 Device의 멤버에서 RT, DSTex, Clear, OMSet 함수를 삭제한다.
RT, DSTex를 Device에서 삭제하긴 했으나, Device의 CreateView 함수에서 여전히 RT, DSTex 용 텍스처를 생성하긴 한다. 해당 텍스처는 리소스로서 엔진에서 생성되기 때문에, RenderMgr의 init함수에서 해당 리소스의 키로 SwapChain용 MRT를 생성하자.
또한 RenderMgr의 render함수 호출 시 OMSet, Clear 함수를 MRT의 함수로 교체해준다.
Clear함수의 경우 가지고 있는 RenderTarget의 개수만큼 반복문을 돌며 모든 RT를 인자로 들어온 색상으로 초기화할 것이다.
RenderMgr이 이제부터 MRT를 관리하게 되는 것이므로 잊지 말고 RenderMgr의 소멸자에서 m_MRT를 지워주도록 한다.
근데 우리의 Present 함수는 SwapChain 내의 함수로, 이는 SwapChain이 가지고 있는 RenderTarget에 출력하는 함수이다. 우리가 아무리 MRT를 새로 만들어도, Present 함수는 항상 SwapChain이 관리하는 것에만 출력을 하는 것이 아닐까?
->이로 유추할 수 있는 것은, 우리가 만들 SwapChain Type 외의 다른 MRT들은 실제로 최종 출력하여 우리가 눈으로 볼 것들이 아니라는 소리이다.
이 MRT들을 실제 눈으로 확인하려면 ImGui 내에서 텍스처화해서 봐야 한다.