유니티 엔진에서 기존 메인 카메라 clipResults 를 사용해서 특정 행렬을 기준으로 객체 모두 다시 렌더링하기 - Whitmem
유니티 엔진에서 기존 메인 카메라 clipResults 를 사용해서 특정 행렬을 기준으로 객체 모두 다시 렌더링하기
게임 개발 및 엔진
2026-01-09 21:24 게시 e4ce06b1f0bb6dca94e3

0
0
44
이 페이지는 외부 공간에 무단 복제할 수 없으며 오직 있는 그대로 게시되며 부정확한 내용을 포함할 수 있습니다. 법률이 허용하는 한 가이드 라인에 맞춰 게시 내용을 인용하거나 출처로 표기할 수 있습니다.
This page is not to be distributed to external services; it is provided as is and may contain inaccuracies.
저작물 참고 필자도 해당 내용을 공부하고 있는 입장으로 주로 오픈 문서, 포럼, AI 질의 응답을 활용하여 관련 내용을 공부하였습니다. 따라서 틀린 내용이 있을 수 있습니다. 다만, 타인(AI 등)의 저작물을 침해하지 않도록 순서, 과정, 스크린샷, 코드 등 다른 저작물을 활용 또는 포함하지 않았으며, AI 등 인터넷 자료는 오로지 기술 원리 이해의 목표로만 활용하고, 본 게시글에 언급된 과정, 흐름, 본문, 게시한 코드는 AI의 복붙 없이 모두 필자가 사전에 알고 있는 그래픽스 기술과 인터넷 상에 공개된 개념을 통해 모두 직접 시도하며 직접 작성하였음을 밝힙니다. 부득이하게 어떤 자료를 인용하는 경우는 링크로 출처를 남기고 인용합니다.
이전 게시글 https://whitmem.kr/read/527 에서 이어집니다. 본론부터 말하자면 이 부분이 제일 힘들었다... AI 질문을 해보아도 구버전 답변만 해주고, 어찌 저찌 새로운 Cull 을 하면 전체 크래시가 떠버려 프로그램이 응답 없음 꺼지는 증상이 발생했었다.
결과적으로 완전히 새로운 Cull을 만드는 것이 아니라 기존 cullResults 를 활용해서 특정 행렬에서 새로 렌더링하기로 하였다. 새로 Cull을 안 만들어도 됐던 이유는 어차피 화면 상에 보이는 객체들에 대해서만 그림자 맵 처리가 진행되면... 됐기 때문이다... (물론 미세하게 다른 부분이 있겠지만 말이다.)
RenderListDesc
화면상에 보이는 객체를 C# 스크립트에서 for 문으로 하나씩 렌더링 할 수 있겠지만 내부 C++ 호출이 아니기 때문에 성능 상 문제가 발생할 우려가 있다. 따라서 엔진이 제공하는대로 Cull 하여 CullResults 를 얻고 CullResults 에 대해서 일괄 출력 요청을 내부 엔진에 전송해야 한다.
Cull 이란 모든 객체를 바로 그래픽 라이브러리에 Draw Call 하는 경우 메시 개수에 따라 성능 문제가 발생할 수 있기 때문에, 우선 화면 절두체 범위 내에 들어오는 객체들만 뽑아내는 역할을 한다.
Cull OFF 되어 있으면 무조건 이 Cull Results에 들어올 것으로 보인다.
RendererListDesc desc = new RendererListDesc(new ShaderTagId("UniversalForward"), renderingData.cullResults, cameraData.camera);
일단 RenderListDesc 는 3개의 인자를 요구하는데, ShaderTagId, CullResults, Camera 이다.
일단 내가 그리고자 하는 것은 광원 기준 행렬이기 때문에 카메라가 존재하지는 않는다. 렌더 과정에서 카메라의 속성 정보도 같이 렌더러에 넘겨주기 위함으로 보이는데, 일단 기본 카메라로 넘겨주고 필요한 부분은 쉐이더 파라메터로 직접 조절하는 방식을 사용하기로 결정하였다.
ShaderTagId 는 옆 인자 CullResults 로 들어온 컬 객체들 중 렌더할 때 ShaderTagId 라는 LightMode tag 를 가지는 패스를 모두 렌더한다고 보면된다. (실제 일반 Lit Material을 생성후 Edit 를 들어가면 LightMode 로 UniversalForward 가 선언되어 있는 것을 확인할 수 있다.) 이렇게 만든 desc 를 바탕으로 CreateRenderList 하면 된다.
다만 막상 이렇게 요청하면 오류가 발생하는데 renderQueueRange 를 지정하지 않았다고 오류가 발생한다. 우선 눈에 보이는 불투명 객체에 대해서 렌더하는 것이 주요 목표이기 때문에 opaque 모드로 desc에 명시한다.
이렇게 RendererListHandle 즉 rtHandle 변수를 만들어 렌더러 리스트에 담아주었다. 참고로 rtHandle이라는 변수명은 틀린 것이다.... RenderTarget 을 하도 많이 만들어서 rtHandle 이라는 변수명을 모르고 사용해버렸다.
아무튼, 이렇게 만든 RendererList 는 이제 이 RasterPass 단위인 Builder 에게 주요 Renderer 로 사용할 것이라고 알려줘야 한다.
아무래도 GPU 메모리 공간으로 올릴 수 있도록 스위칭하는 역할이 아닌가 추정된다.
그리고 마지막으로 Execute 에서 실행할 수 있도록 passData로 넘겨준다.
마지막으로 이제 실제 ExecutePass 에서 현재 커맨드 버퍼에 출력 요청을 보내주면 된다.
위와 같이 해주면 일단 에디터 상에서는 일반 모드로 보인다.
노란색 객체는 실제 Hierarchy에 존재하는 것이 아니다. 직접 그래픽 출력 요청을 통해 라이브러리로 출력된 것이다. 이제 게임 뷰에서 보면 아래와 같다.
처음 보면 결과가 헷갈릴 수 있는데 내가 별도 렌더 타겟을 만들어서 출력한 것이 아니라 메인 카메라 영역에 출력한 것이기 때문에 카메라의 기본 출력 결과에 덧 붙여서 출력됐다고 봐야 한다. 즉 내 Render Pass 쪽에서는 먼저 아래 객체 3개가 그려진 것이다. (이전 게시글에서 DrawMesh도 했기 때문이다.)
이 3개 객체는 광원 좌표 기준 (30, 30, 30) 기준에서 렌더링한 것이다. 그외 2개 객체는 기본 카메라에서 ActiveColor 영역에 렌더링 된 것이다.
즉 렌더 패스 영역에서 이후 Pass 되는 각 객체를 직접 컨트롤할 수는 없기 때문에 이거대로 그려지고, 내가 만든 렌더 패스에서 컬링된 객체 3개가 출력된 것이다. 이것을 나중에 렌더 타겟으로 빼 내면 광원에서 3개만 쳐다보는 깊이 버퍼 등을 만들 수 있을 것이다. 해당 부분은 다음 게시글에서 직접 구현하고 기록하고자 한다.
댓글 0개
댓글을 작성하는 경우 댓글 처리 방침에 동의하는 것으로 간주됩니다. 댓글을 작성하면 일회용 인증키가 발급되며, 해당 키를 분실하는 경우 댓글을 제거할 수 없습니다. 댓글을 작성하면 사용자 IP가 영구적으로 기록 및 부분 공개됩니다.
확인
Whitmemit 개인 일지 블로그는 개인이 운영하는 정보 공유 공간으로 사용자의 민감한 개인 정보를 직접 요구하거나 요청하지 않습니다. 기본적인 사이트 방문시 처리되는 처리 정보에 대해서는 '사이트 처리 방침'을 참고하십시오. 추가적인 기능의 제공을 위하여 쿠키 정보를 사용하고 있습니다. Whitmemit 에서 처리하는 정보는 식별 용도로 사용되며 기타 글꼴 및 폰트 라이브러리에서 쿠키 정보를 사용할 수 있습니다.
이 자료는 모두 필수 자료로 간주되며, 사이트 이용을 하거나, 탐색하는 경우 동의로 간주합니다.