https://gall.dcinside.com/mgallery/board/view/?id=game_dev&no=187380
ㅎㅇㅎㅇ지난번에 윈도우 다루기에 이어서, 이번에는 디바이스(GPU)를 다루는 방법에 대해서 써볼까 함지난글https://gall.dcinside.com/mgallery/board/view/?id=game_dev&
gall.dcinside.com
오늘은 지난 글에 이어 스왑체인과 쉐이더, 파이프라인, 렌더패스, 버퍼들에 대해서 다룰 예정임
지난 글에서 GPU를 다루는 단계까지 갔기 때문에, 이를 이용해 각종 GPU 자원들을 생성해보고 렌더링을 해보겠음
우선 설명은 지난 글과 마찬가지로 먼저 Vulkan을 기반으로 하며, 이후에 WGPU와 WebGPU, WebGL까지 이어가보겠음
그래픽스를 처음 다룬다면 스왑체인이란 개념이 생소할 수도 있음... 최대한 쉽게 설명해보자면...
그래픽을 화면에 표시하기 위해서는 버퍼에다가 데이터를 입력하고 이 입력된 데이터를 표시해줘야 하는데,
만약 이게 동시에 일어나게 되면 컴퓨터 화면에 아직 다 그려지지 않은 그래픽이 표시되는 문제가 생길 수도 있음
오래전 80~90년대 초창기 그래픽 시스템에선 그래서 화면이 깜빡거리거나 깨지는 현상이 발생되곤 했음ㅇㅇ
그래서 이러한 문제를 해결하고자 버퍼를 미리 몇개를 만들어두는거임.
예를 들어 버퍼가 3개가 있다면, 모니터에는 가장 마지막에 그려진(이미 완성된) 버퍼만 출력시키게 하고,
실제 우리 프로그램에서는 최신 버퍼에만 계속 입력을 하는거임ㅇㅇ 즉 앞에서 넣고 뒤에서 꺼내는 구조(큐 처럼, FIFO)
그러면 아주 미세한 지연이 생기지만, 화면이 깨지지 않고 잘 출력되게 됨
이런걸 총괄하는게 스왑체인 시스템임.
우리 엔진에서 스왑체인과 관련된 내용을 추상화해둔 코드는 다음과 같음
https://github.com/erenengine/eren/blob/main/eren_vulkan_render_shared/src/swapchain.rs
다음 버전의 에렌엔진을 작업하는 소스코드 저장소입니다. Contribute to erenengine/eren development by creating an account on GitHub.
github.com
1. 디바이스에서 스왑체인을 만들고,
2. 스왑체인에서 그려질 이미지를 확보하고,
3. 그 이미지를 다룰 이미지 뷰를 만들고,
4. 그 뷰에 데이터를 쓰도록 버퍼를 생성하고,
5. 추후 렌더링 단계에서 현재 쓸 이미지 순번을 매번 가져와서 거기다가 쓰는 구조임
이미지 순서가 보장되도록 하기 위해 세마포어나 펜스 등의 개념들도 존재하지만 설명이 너무 복잡해질 것 같아서 뺌...
이제 명령을 내려서 실제로 화면에다가 뭐라도 그려봐야겠지?
명령을 내리기 위해서는 커맨드 버퍼라는걸 만들고 거기다가 명령을 쓰고, GPU에 넘기면 됨
근데 Vulkan에서는 이 커맨드 버퍼들을 통합으로 다루기 위해, 커맨드 풀이라는 개념이 있음
여기서 커맨드 버퍼를 할당하고 관리함
커맨드 풀 추상화 코드(보면 알겠지만 커맨드 버퍼를 할당하는 기능 뿐임)
https://github.com/erenengine/eren/blob/main/eren_vulkan_render_shared/src/command.rs
이제 이렇게 만들어진 커맨드 버퍼에다가 명령을 써갈겨야겠지?
커맨드 버퍼에다가 명령을 써갈기기 위해서는 렌더 패스라는 놈이 필요함
렌더 패스는 화면에 무엇을 어떤 순서로 그릴지를 정의하는 틀 같은 개념임
그리고 서브패스는 이 렌더 패스에 들어가는 세부적인 단계별 그리기 작업 단위임
즉 렌더 패스는 서브패스들의 집합으로, 단계별 그리기를 모아 프레임 단위로 화면을 그리는 녀석임
또 첨부라는 개념이 있는데... 색상, 깊이, 스텐실 등 종류 단위로 그릴 대상을 쪼개 패스에 전달하는 개념임... 자세히 설명하면 너무 길어지니 패스.
아래는 테스트 용으로 만들어본 렌더 패스와 서브 패스임
렌더 패스
Rate limit · GitHub
github.com
서브 패스
https://github.com/erenengine/eren/blob/main/eren_vulkan_render_shared/examples/test_pass/subpass.rs
다음 버전의 에렌엔진을 작업하는 소스코드 저장소입니다. Contribute to erenengine/eren development by creating an account on GitHub.
github.com
파이프라인은 이제 실제로 그리기의 명령을 지니고 있음.
한 서브패스에는 여러개의 파이프라인을 설치할 수 있음.
즉, 서브패스는 "어디에 쓸지"와 파이프라인들의 집합이고, 파이프라인은 "어떻게 쓸지"에 대한 내용을 담음 (그리고 랜더 패스는 서브패스의 집합)
이제 여기서 쉐이더 개념이 등장함ㅇㅇ
쉐이더는 GPU상에서 실행되는 프로그래밍 가능한 동작 명세임
쉐이더는 또 두가지로 나눌 수 있는데(실제로는 더 많지만 여기선 두개만 설명)
정점 쉐이더와 프래그먼트 쉐이더가 그것임
정점 쉐이더는 위치데이터를 다루고 프래그먼트 쉐이더는 색상데이터를 다룸
우리가 예시로 쓸 정점 쉐이더 코드와,
다음 버전의 에렌엔진을 작업하는 소스코드 저장소입니다. Contribute to erenengine/eren development by creating an account on GitHub.
github.com
프래그먼트 쉐이더 코드
다음 버전의 에렌엔진을 작업하는 소스코드 저장소입니다. Contribute to erenengine/eren development by creating an account on GitHub.
github.com
그냥 단순히 화면에 삼각형을 그려주게 만들어봄ㅇㅇ
이제 이렇게 만들어진 모든 코드들을 바탕으로, 렌더러를 구축하고 전체 프로그램을 실행해볼 것임
렌더러 코드
다음 버전의 에렌엔진을 작업하는 소스코드 저장소입니다. Contribute to erenengine/eren development by creating an account on GitHub.
github.com
전체 실행 코드
https://github.com/erenengine/eren/blob/main/eren_vulkan_render_shared/examples/test_pass.rs
다음 버전의 에렌엔진을 작업하는 소스코드 저장소입니다. Contribute to erenengine/eren development by creating an account on GitHub.
github.com
그럼 아래처럼 삼각형이 잘 나옴
색상이 그라데이션인데, 이건 GPU에서 자동으로 색상을 보간해주기 때문임ㅇㅇ
WGPU는 Vulkan과 다르게 많은 부분을 내부적으로 처리해주기 때문에, 상대적으로 코드량이 매우 가벼움
아예 스왑체인 관련 코드가 "없음"ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
그리고 서브패스 개념도 "없음"ㅋㅋㅋㅋ
그냥 렌더패스들만 가지고 구현해야 함ㅋㅋ
물론 핵심적인 파이프라인과 쉐이더 개념들은 전부 그대로 있음
WGPU용 전체 테스트 코드는 다음과 같음
https://github.com/erenengine/eren/blob/main/eren_render_shared/examples/test_pass.rs
다음 버전의 에렌엔진을 작업하는 소스코드 저장소입니다. Contribute to erenengine/eren development by creating an account on GitHub.
github.com
아래는 쉐이더 코드. WGSL이라는 WebGPU 명세 언어를 사용 (정점 쉐이더와 프래그먼트 쉐이더를 단일 파일에 기록할 수 있음)
Rate limit · GitHub
github.com
얘도 똑같이 잘 나옴ㅇㅇ
Vulkan과의 차이점이 있다면, 좌표계가 달라서 Y축이 반대방향임. 그것만 별도로 처리해주면 됨
WGPU는 wasm도 지원하기 때문에, wasm으로 웹버전도 만들어봤음
https://erenengine.github.io/eren/eren_render_shared/examples/test_pass.html
WASM Test pass
erenengine.github.io
잘 나옴ㅇㅇ (배경 색이 어두운데, 이건 아직 크롬의 WebGPU가 sRGB를 지원하지 않기 때문임)
WGPU에서와 거의 똑같음ㅇㅇ WGPU에서 쓰던 쉐이더 코드마저 같은걸 씀
WebGPU용 전체 테스트 코드는 다음과 같음. 매우 단촐함 ㅋㅋ
https://github.com/erenengine/erenjs/blob/main/eren-webgpu-render-shared/examples/test-pass/index.ts
Contribute to erenengine/erenjs development by creating an account on GitHub.
github.com
쉐이더 코드는 아래처럼 WGPU꺼랑 완전 똑같은걸 씀
Contribute to erenengine/erenjs development by creating an account on GitHub.
github.com
결과물 (WebGPU를 지원하지 않는 환경, 예를 들어 모바일 등에서는 안나올 가능성이 큼)
http://erenengine.github.io/erenjs/eren-webgpu-render-shared/examples/test-pass/index.html
Test Pass 1
erenengine.github.io
WebGL에선 충격적일 정도로 단촐한데, 그냥 뭐 아무것도 없고 쉐이더를 "프로그램"이란 단위로 묶어서 너, 사용! 하기만 하면 끝임
진짜임...
전체 테스트 코드
https://github.com/erenengine/erenjs/blob/main/eren-webgl-render-shared/examples/test-pass/index.ts
Rate limit · GitHub
github.com
결과물
https://erenengine.github.io/erenjs/eren-webgl-render-shared/examples/test-pass/index.html
Test Pass 1
erenengine.github.io
여기까지 Vulkan, WGPU, WebGPU, WebGL로 화면에 뭔갈 그려보았음
아주 단순한 삼각형을 그리기까지 수많은 개념들이 필요했음;;
다음번엔 막 3d로 좀 더 멋진걸 그려보도록 하겠음ㅋㅋㅋㅋㅋㅋ
그럼 모두 작업 홧팅이야!!!
정보추
유니티언리얼고도겜메쯔꾸르 게섯거라
그들은 신이야...!