일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 인터페이스
- callbyreference
- 게임
- Unity
- 확장메서드
- 게임개발
- 깃허브
- 게임제작
- Euler
- 델리게이트
- C#
- ExtensionMethod
- ARProgect
- 1인개발
- 리듬게임에디터
- 유니티
- 레이캐스트
- 소규모프로젝트
- 로케트
- AR Foundation
- AR게임
- raycast
- 짐벌락
- AR세팅
- 리듬게임
- callbyvalue
- github
- 병맛게임
- ar
- Quaternion
- Today
- Total
Ssssong += Dev
[유니티/DirectX/OpenGL] 셰이더 본문
0. Materials / Shaders / Textures
https://docs.unity3d.com/kr/530/Manual/Shaders.html
Materials : 사용되는 텍스처에 대한 레퍼런스, 타일링 정보, 컬러 틴트 등을 포함한 표면 렌더링 방법의 정의
사용 가능 옵션은 머리티얼에 사용하는 셰이더에 따라 달라진다.
Shaders : 조명 입력과 머티리얼 설정에 따라 렌더링된 각 픽셀의 컬러를 계산하는 수학적 계산식 및 알고리즘이 포함된 스크립트
Textures : 비트맵 이미지.
1. HLSL과 GLSL
HLSL(Hight - Level Shader Language) : DirectX에서 프로그래밍 가능한 셰이더와 함께 사용하는 C와 유사한 상위 수준 셰이더 언어이다.
고수준의 언어이기에 가독성이 좋고 관리에 이점이 있다.
GLSL : OpenGL의 표준 셰이딩 언어이며 개발자가 그래픽스 파이프라인을 직접 제어할 수 있는 언어이다.
매킨토시, 윈도, 리눅스 등 여러 운영체제 간의 호환성을 지원한다.
GLSL에서 Shader의 진입 함수로 main() 함수가 사용되나 HLSL은 그 함수 이름이 main으로 고정되지 않고 직접 정의 가능하다.
GLSL에서는 Vertex Shader와 Pixel Shader에 각각 main 함수가 있어야 하기에 두 파일을 따로 컴파일하여야 하지만
HLSL에서는 진입호출 함수를 직접 정할 수 있으므로 하나의 파일로 관리가 가능하다.
HLSL에서는 GLSL과 달리 Semantics가 있어야 한다. 시멘틱은 해당 변수의 성격을 정해준다.
[출처]
https://gpututorial.blogspot.com/2018/01/semantics-in-hlsl.html
이 글에 나와있는 것과 같이 Semantic은 변수들이 어떤 자료와 연결될 지 알려주는 것이다.
대표적으로 SV_Position(레스터라이즈 이전 셰이더에서 출력)과 SV_Target(버텍스 셰이더에서 출력)이 있다.
픽셀셰이더의 경우 출력으로 SV_Delth와 SV_Target만 사용할 수 있다.
DirectX HLSL에서의 시멘틱 의미 문서
2. Rendering Pipeline
[출처]
https://parodev.tistory.com/30
3D 컴퓨터 그래픽스에서 그래픽스 파이프라인(렌더링 파이프라인)이란 3차원 도형 혹은 이미지를 래스터 이미지로 표현하기 위한 단계적 방법을 의미한다.
3. Vertex Shader와 Fragment Shader
vertex buffer data는 vertex 정보를 가지고 있는 메모리 블럭이다. 위치, 색상, 텍스처 등의 정보를 가지고 있다.
Vertex Shader는 이런 vertex data를 받아 각 점을 생성한다.
Fragment Shader는 레스터라이제이션을 통해 생성된 fragment를 처리한다.
*Fragment Shader를 Pixel Shader라는 용어로 혼용해서 사용하기도 하긴 하는데
검색해보니 fragment로 생성된 상태에서 동작하지 '아직' pixel 상태가 아니기 때문에 Fragment Shader라는 말이 더 적합해 보인다.
-> 집에 있는 DirectX 책 좀 찾아봐야겠는걸...
[출처]
https://gpututorial.blogspot.com/2018/01/vertex-shader-and-pixel-shader-glsl.html
* GLSL에서 uniform / attribute / varying
- uniform은 전역 변수와 같은 역할. vertex shader와 fragment shader에서 모두 공유할 수 있지만 값을 읽는 것만 가능하다.
- attribute는 vertex shader에서만 사용 가능하다.
- varying은 vertex shader에서 fragment shader로 값을 전달하는 경우에 사용한다.
4. SubShaderLab
유니티 공식메뉴얼 ShaderLab 구문 사용법
https://docs.unity3d.com/kr/530/Manual/SL-Shader.html
https://jinhomang.tistory.com/43
유니티에서 사용하는 셰이더 스크립트 언어이다. 유니티는 멀티플랫폼 엔진이기 때문에 다양한 플랫폼과 디바이스에 대응해야 하고, 따라서 공통의 인터페이스가 요구되므로 이러한 언어를 사용한다.
유니티 셰이더 파일은 하나의 Shader 블럭이 있고 그 안에 여러 SubShader가 있는 형태로 구성된다.
여러 SubShader를 통한 구현을 할 수 있게 구성된 이유는 그래픽 하드웨어의 다양성 때문이다. 어떤 셰이더가 특정 하드웨어에서 지원되지 않아 동작하지 않는 현상을 막는다.
Fallback은 모든 SubShader들이 동작하지 않는 경우 지정된 이름의 셰이더를 찾아 적용해준다.
Pass는 셰이더에서 렌더링 단위를 의미한다. 따라서 SubShader 안의 Pass 수 만큼 오브젝트가 렌더링된다.
URP에서 사용하는 Pass tags는 유니티 문서를 참고하면 된다.
5. Rendering path
https://docs.unity3d.com/kr/530/Manual/RenderTech-DeferredShading.html
https://learn.unity.com/tutorial/understanding-rendering-paths-2019-3?signup=true#
https://learnopengl.com/Advanced-Lighting/Deferred-Shading
Deferred Rendering
- 자연 빛! 가장 높은 빛과 그림자 충실도를 가졌다. 실시간 빛이 많을 때 사용하면 좋다.
- 첫 패스에 전부 계산해서 렌더한다.
- 광원의 수보다 광원의 영향을 받는 픽셀 기준으로 렌더 코스트가 생긴다.
- 높은 하드웨어 사양이 요구된다.
- Orthographic(직교 투영)에서는 디퍼드 렌더링을 지원하지 않는다.
Forward Rendering
- 각 오브젝트에 영향을 미치는 가장 밝은 광원이 픽셀당 릿 모드에서 완전히 렌더링되고 다음 광원이 최대 4개까지 버텍스 당 릿 모드로 렌더링된다. 마지막으로 나머지 광원이 스피리컬 하모닉스(SH)로 렌더링된다.
- 셰이더에 기반을 둔 렌더링이다.
- 광원의 수에 따라 오브젝트가 여러번 렌더링 될 수 있다. 따라서 광원이 많으면 렌더 시간이 늘어난다.
- 렌더링 속도가 빠르다.
6. LightMode 태그
https://docs.unity3d.com/kr/530/Manual/SL-PassTags.html
조명 파이프라인에서 패스가 담당하는 역할을 정의한다.
셰이더 연산 순서
출처 : 유니티 도큐먼트
7. 셰이더 배리언트
공통 코드를 공유하는 셰이더에서 특정 키워드의 활성화 여부에 따라 다른 기능을 갖게 할 수 있다.
활성/비활성화된 키워드의 다양한 조합에 대해 생성된 별도의 셰이더 프로그램을 셰이더 배리언트라고 한다.
https://docs.unity.cn/kr/2020.3/Manual/SL-MultipleProgramVariants.html
#pragma는 컴파일에게 그 뒤에 오는 내용에 따라 어떤 일을 하라는 전처리 명령이다.
[출처]
https://chulin28ho.tistory.com/591
#pragma shader_feature
#pragma multi_compile
shader_feature 셰이더의 사용되지 않는 배리언트가 게임 빌드에 포함되지 않는다.
- 머티리얼에 설정되는 키워드에 가장 적합 (Emmision 연산을 할 것인지, 해당 머테리얼에서 노말맵을 쓸 것인지 등등)
- runtime에 변경되지 않는 경우!
multi_compile
- 코드에서 전역으로 설정되는 키워드에 적합(라이트가 있는지, 섀도우가 있는지 등등)
- runtime에 enable, disable로 변경할 수 있는 경우 빌드에 포함시켜야 하므로 설정하는 키워드
#pragma shader_feature_local
#pragma multi_compile_local
로컬 지시문은 정의된 키워드를 전체 프로젝트에 적용하는 대신 해당 셰이더에 보관한다.
전역 API를 통해 특정 키워드 활성화하려는 경우를 제외하고는 로컬 키워드 쓰는 게 성능상으로 이득이다.
- 한계
- 전역 키워드를 변경하는 API가 포함된 로컬 키워드(예: Shader.EnableKeyword 또는 CommandBuffer.EnableShaderKeyword)는 사용할 수 없습니다.
- 셰이더당 최대 64개의 고유 로컬 키워드를 사용할 수 있습니다.
- 머티리얼에 활성화된 로컬 키워드가 있고 해당 셰이더가 더 이상 선언되지 않는 셰이더로 변경되면 Unity는 새로운 전역 키워드를 생성합니다.
8. URP
-> 기존 Unity 빌트인 렌더 파이프라인을 사용하면 포워드 렌더링 경로와 디퍼드 렌더링 경로 중 하나를 택할 수 있었다.
하지만 커스텀 렌더링 전략은 추가할 수 없었고 기존 인젝션 포인트에서만 기존 전략을 확장할 수 있었다.
유니버설 렌더 파이프라인은 렌더러 개념을 도입함으로써 확장성이 향상되었다.
설정 시 파이프라인 에셋에 렌더러 목록을 선언하고 각 카메라에서 렌더러를 사용할 수 있다.
직접 렌더러를 만들고 파이프라인을 확장할 수 있다.
[출처]
https://blog.unity.com/kr/technology/how-the-lightweight-render-pipeline-is-evolving
'개발 > 공부' 카테고리의 다른 글
[유니티] Gamma와 Linear (0) | 2022.11.02 |
---|---|
[유니티/젠킨스] Jenkins (0) | 2022.10.28 |
[유니티] SerializedObejct (0) | 2022.10.06 |
[C#] C# Coding Conventions (0) | 2022.09.14 |
[C#] Flag연산 (0) | 2022.09.14 |