티스토리 뷰
이번에는 저번 시간에 이어서 Unity SRP를 이용해 Object를 그리는 방법에 대해서 알아보겠습니다.
저번 시간과 마찬가지로 결과 화면 먼저 보겠습니다.
역시나 저번 포스팅과 비슷하게 그래픽스 수업 시간 초반에 나올법한 이미지입니다.
기존 유니티를 이용해 씬에 GameObject를 배치하면 이런 식으로 나오지 않았기 때문에 조금 생소할 수 있습니다.
유니티에서 기본적으로 GameObject를 생성하면 Lighting이 된 Object가 배치됩니다.
하지만 이번 시간에 만들어진 Object는 빛과 관계없이 모든 면이 단색으로 같습니다.
유니티에서는 이렇게 빛의 영향을 받지 않고 색이 결정되는 Material을 Unlit이라고 합니다.
하얀색 Object의 경우도 점 마다 투명도가 다를 뿐 색은 기본적으로 모두 똑같은 하얀색입니다.
*거미줄 같은 텍스쳐는 포스팅 맨 아래의 참고 자료에서 제공하는 이미지를 사용했습니다.
조금 부가 설명하면 하얀색 Object는 Unlit(빛에 영향 받지 않는) Transparent(투명한) Material을 사용했고
나머지 Object는 Unlit(빛에 영향 받지 않는) Opaque(불투명) Material을 사용했습니다.
유니티는 기본적으로 Opaque와 Transparent를 나눠서 처리하는데 그 이유는 화면에 Rendering 결과로 색을 그리는 과정과 연관이 있습니다.
다시 정리해서 이번 글의 목표는 아래 3가지로 간단합니다.
1. 매 Render 마다 화면을 Clear하기
2. Opaque Object들 그리기
3. Transparent Object들 그리기
매 Render 마다 화면을 Clear 하기
이제 본격적으로 시작해보겠습니다.
가장 먼저 해야할 일은 Command Buffer라는 것을 만들어서 Rendering 관련된 명령들을 만들고 실행할 수 있도록 하는 것입니다.
전 포스팅에서는 ScriptableRenderContext를 이용해 간단하게 Skybox를 그렸습니다.
하지만 조금 복잡한 Rendering 명령을 이용하려면 Command Buffer를 이용해야 합니다.
아래 코드는 Command Buffer를 사용해서 Render Target을 Clear하고 Skybox를 Render하는 코드입니다.
CustomRenderPipeline.cs 파일을 열어서 Render() 함수를 아래와 같이 수정합니다.
buffer와 sampleName은 CustomRenderPipeline 클래스의 멤버변수로 아래와 같이 초기화하면 됩니다.
코드가 많이 추가된 것 같지만 크게 보면 3가지입니다.
1. buffer의 ClearRenderTarget 함수
2. buffer의 BeginSample, EndSample 함수
3. context의 ExecuteCommandBuffer 함수와 buffer의 Clear 함수
1. 일단 buffer의 ClearRenderTarget() 함수는 말 그대로 Render Target을 Clear하는 함수입니다.
여기서 Render Target은 단순히 그려질 화면이라고 생각하면 됩니다.
Render Target은 보통 Color Buffer와 Depth Buffer로 이루어져있는데 모두 Clear할 것인지와 어떤 값으로 Clear할 것인지에 대한 값을 인자로 보내면 됩니다.
2. BeginSample() 함수와 EndSample()는 쌍으로 맞추어야하는 함수이고 인자로 보내는 sampleName 변수를 똑같게 해서 쌍을 맞출 수 있다고 설명되어 있습니다. 하지만 딱히 어떤 용도로 쓰이는지는 확실히 파악하기 힘들었습니다.
BeginSample과 EndSample이 있고 없고의 차이는 Frame Debugger에서 화면을 Clear하고 Skybox를 그리는 Render Loop가 묶여있냐 아니냐 정도였습니다.
3. ExecuteCommandBuffer 함수와 buffer의 Clear 함수는 대체로 묶여서 실행되는 함수입니다.
context의 ExecuteCommandBuffer 함수는 Command Buffer를 인자로 갖고 Command Buffer에 예약된 명령들을 Execute하는 함수입니다. 단, 함수가 실행됐다고 Command Buffer의 명령들이 Clear되지 않습니다. 따로 Clear를 통해 Buffer를 비워주어야 다음에 문제없이 사용할 수 있습니다.
코드를 조금 추가했지만 결과 이미지는 저번 포스팅과 다를 바 없습니다.
실제로 Object들을 그리려면 당연하게 그리는 코드를 추가해야 합니다.
Opaque, Transparent Object들 그리기
가장 위에 보이는 이미지를 만들기 위해서는 아래와 같은 코드들을 추가해야 합니다.
SetupCameraProperties 함수 위에 Culling하는 코드를 넣습니다.
결론적으로는 실제로 Draw를 할 때 사용되는 cullingResults를 얻기 위함입니다.
Culling은 개념적으로 설명하면 카메라에 보이는 Object 들만 추리는 과정입니다.
카메라 정보로부터 Culling에 관련된 Parameter를 얻을 수 있고 이 Prameter를 통하면 CullingResults를 얻을 수 있습니다.
CullingResults에는 아마 카메라에 보이는 Object들에 관한 정보나 Light 정보등이 있을테지만 직접적으로 Mesh나 Vertex에 접근할 수는 없습니다.
Culling과 SetupCameraProperties에 이어서 Rendering을 합니다.
여기서 핵심 함수는 DrawRenderers입니다.
DrawRenderers는 CullingResults, DrawingSettings, FilteringSettings를 인자로 받습니다.
CullingResults는 아까 Culling을 통해 만들었고 DrawingSettings는 Shader Tag Id와 SortingSettings를 통해 만들 수 있습니다.
여기서 사용된 Shader Tag Id는 아래와 같은 String Literal을 이용해서 만들어야 합니다.
주의해야할 것은 위 코드에서 DrawRenderes가 2번 불린다는 것입니다.
단, 2번째 불릴 때는 사용되는 Parameter들의 값이 다르고 Skybox가 그려진 후에 불립니다.
그 이유는 Opaque와 Transparent는 조금 다른식으로 처리해야하기 때문입니다.
먼저 SortingSettings, DrawingSettings, FilteringSettings에 대해서 간단히 살펴봅시다.
SortingSettings
Sorting Settings은 말 그대로 정렬에 관한 Setting들입니다.
Opaque와 Transparent의 가장 큰 차이는 Opaque 물체들을 Rendering을 할 때 카메라와 가까운 물체부터 먼 물체 순서로 그리고 Transparent를 Rendering할 때는 카메라와 먼 물체부터 가까운 물체 순서로 그립니다.
이렇게 하는 순서는 조금 생각해보면 알 수 있습니다.
Opaque 물체는 기본적으로 뒤 쪽에 있는 물체가 보이지 않습니다.
따라서 카메라와 가까운 곳에서부터 먼 곳으로 그리면 가까운 곳에 물체가 있어서 뒤 쪽에 있는 물체를 가리는 경우 뒤 쪽의 물체를 그릴 필요가 없습니다.
반면 투명한 물체는 뒤쪽에 물체가 보입니다.
투명한 물체를 랜더링을 할 때는 보통 뒤쪽의 물체를 그려서 이미 화면에 채워진 색을 합쳐서 색을 구해서 그립니다. 따라서 뒤에서 앞 순서로 그리게 됩니다.
DrawingSettings
Drawing Settings는 어떤 Sorting Settings를 사용할 것인지 어떤 Shader Pass를 사용할 것인지 결정합니다.
Drawing Settings에서 설정되지 않은 Shader를 이용한 Object들은 해당 Drawing Settings으로 Draw할 때 그려지지 않습니다.
Filtering Settings
Filtering Settings는 특정 Object들만 그릴 수 있도록 합니다.
보통의 경우 Transparent와 Opaque를 나누고 다른 타이밍에 그려지도록 하기 위해 사용됩니다.
그리는 순서
이번 예제에서는 Opaque -> Skybox -> Transparent 순서로 그려지고 있습니다.
그 이유에 대해 간단하게 설명하면 Skybox와 Transparent는 Z Write를 하지 않고 Z Test만 합니다.
Z Write를 하지 않는다는 것은 Depth Buffer에 값을 쓰지 않아서 이 물체 뒤에 오는 물체가 가려지지 않도록 한다는 뜻이고 Z Test를 한다는 것은 물체 뒤에 있을 경우 가려져서 보이지 않을 수 있다는 것입니다.
보통 Opaque의 경우 Z Test, Z Write를 모두 합니다.
Transparent의 경우 Z Test만 하고 앞, 뒤 구분은 그려지는 순서로 결정합니다.
예제에서는 가장 먼저 Opaque를 그립니다. 그러면 Depth 값이 채워집니다.
그 다음으로는 Skybox를 그립니다. Z Test 덕분에 Opaque 물체 앞에 그려지는 경우가 없게 됩니다.
Z Write를 하지 않아서 나중에 그려질 어떤 물체든 Z Test를 쉽게 통과할 수 있게 합니다.
마지막으로는 Transparent를 그립니다. Z Test 덕분에 Opaque 물체 뒤에 있을 경우 그려지지 않게 되고 Z Write를 하지 않아서 뒤에 그려질 다른 Transparent Object를 완전히 가려버리지도 않습니다.
Scene 구성하기
이렇게까지 했으면 모든 준비가 끝났습니다.
이제 Unity Editor를 이용해 Object들을 Rendering할 수 있습니다.
이제 Hierarchy에서 마우스 오른쪽 버튼 -> 3D Object -> Sphere를 통해 GameObject를 씬에 생성해봅시다.
아쉽게도 아직까지도 결과가 나오지 않습니다.
이유는 방금 만든 GameObject가 위에서 DrawingSettings에 보낸 ShaderTagId("SRPDefaultUnlit")를 사용하는 Material을 사용하지 않기 때문입니다.
해결 방법은 이 "SRPDefaultUnlit"이라는 ShaderTagId를 사용하는 Material을 만들어서 GameObject에 붙여주면 됩니다.
총 4개의 Material을 만들었습니다.
나머지 분홍색과 연두색은 색만 다를 뿐 똑같이 Unlit/Color Shader를 사용했습니다.
이 Material들을 GameObject에 붙여주면 이제 정상적으로 GameObject들이 보입니다.
참고 자료
https://catlikecoding.com/unity/tutorials/custom-srp/custom-render-pipeline/
'Unity' 카테고리의 다른 글
Unity SRP 처음부터 시작하기 3 - 최적화 (3) | 2020.07.19 |
---|---|
큐브 맞추는 기계 살 돈이 없어서 직접 만드는 글 #6 (0) | 2020.07.08 |
큐브 맞추는 기계 살 돈이 없어서 직접 만드는 글 #5 (0) | 2020.07.02 |
큐브 맞추는 기계 살 돈이 없어서 직접 만드는 글 #4 (0) | 2020.06.23 |
Unity SRP 처음부터 시작하기 1 (0) | 2020.06.21 |
- Total
- Today
- Yesterday
- 값 형식
- collision detection
- 루빅스큐브
- batching
- transform
- Transformation
- SRP
- value type
- Unreal
- C#
- CollisionDetection
- normalized device coordinate
- 강화학습
- Mesh
- Unity
- NDC
- VTK
- reference type
- dynamic batching
- Scriptable Render Pipeline
- static batching
- RL
- perspective projection
- 유니티
- MeshProcessing
- 참조 형식
- AABB
- Mesh Processing
- opengl
- RubiksCube
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |