# 1-3 [Rendering Pipeline, Transform]

Ricon·2024년 8월 5일

URP Shader Basic

목록 보기
3/17

본 게시물은 Unity Korea 채널의 URP Shader Training 시리즈와 강의에 사용된 도큐먼트를 공부하며 정리한 게시물입니다.

강의 링크
도큐먼트 링크


HLSL Snippet(HLSLPROGRAM ~ ENDHLSL)

Unity SRP는 주로 HLSL로 작성되며 HLSLPROGRAM으로 시작하며 ENDHLSL로 끝나는 구조를 가지고 있다.

pragma

C언어에서 pragma는 컴파일러가 입력을 처리하는 방법을 지정하는 언어 문법 -> Shader가 어떻게 컴파일 될지를 지시하는 전처리 문법

//예시
#pragma prefer_hlslcc gles

Rendering Pipeline

  1. Input Assembly : GPU는 메모리에서 버텍스 및 인덱스 버퍼를읽고, Vertex가 Tri를 형성하는 방식을 결정 -> 나머지는 Pipeline에 전달
  2. Vertex Shading : 한 번에 하나의 버텍스에서 실행되는 Mesh의 모든 Vertex에 대해 한 번 실행됨.
    여기에서 Vertex를 변환하고 위치를 받은 다음 카메라 및 Viewport 설정을 사용해 화면에서 최종 위치를 계산
  3. Rasterization : Vertex Shader가 삼각형의 각 Vertex에 실행되고 GPU가 화면에 표시될 위치를 알고 있으면 삼각형이 Rasterization되어 개별 픽셀의 모음으로 변환됨
    Vertex별 정보(UV좌표, Vertex Color, Normal등)은 삼각형 Pixel을 통해 보간됨
    (Rasterization된 픽셀은 각 Vertex의 보간된 값을 가지게 된다)
  4. Pixel Shading : 레스터화 된 각 픽셀은 Pixel Shader를 통해 실행(기술적으로는 아직 픽셀이 아닌 Pragment Shader라고 함)
    Material 속성, Texture, 광원등 기타 Parameter를 프로그래밍 된 방식으로 결합해 특정 색상을 얻어 픽셀에 색상 부여
  5. Render Target Output : 마지막으로 픽셀은 Rendering 대상에 쓰여지지만 일부 테스트를 거쳐야 유효하게 된다.
    EX_Depth Test는 이미 렌더링 대상보다 멀리 떨어진 픽셀을 생략할 수 있다.
    이러한 모든 Test(Depth, Alpha, Stencil등)를 통과하면 메모리의 렌더링 타겟에 쓰여지게 됨.
  6. Z Sort 방식 : 렌더링 하는 물체를 카메라 시점으로부터 거리를 Sorting(정렬)하고, 시점으로부터 먼 것부터 순서대로 렌더링 하는 방식
    (Mesh가 겹칠 경우 Sorting Issue 발생)
  7. Z Buffer 방식 : 물체를 Rendering하면서 그 물체까지의 거리를 픽셀(텍셀) 단위로 Depth Buffer에 저장해두고 다음에 렌더링 할때 이미 렌더링 되어 있는 물체의 거리와 렌더링 하려는 물체의 거리를 비교하면서 앞에 있으면 렌더링(반투명의 경우 렌더링 어려움)

Application to Vertex Shader Structure(Attributes)

Input Assembly 단계에서 VertexBuffer에서 필요한 정보를 가져오는 역할을 한다.

//예시
struct VertexInput
{
	float4 vertex : POSITION;
};
Type(s)Name(변경 가능)SemanticNotes
float4vertexPOSITIONLocal 공간(Model 공간)의 정점 위치
float3normalNORMALVertex의 Normal
float4texcoord[n]TEXCOORD[n]Vertex의 UV좌표
float4tangentTANGENTMesh에서 계산된 또는 Import된 Tangent값
float4colorCOLORVertex의 Color값
//예시
LitForwardPAss.hlsl

struct Attributes
{
	float4 positionOS :POSITION;
	float3 normalOS :NORMAL;
	float4 tangentOS :TANGENT;
	float2 texcoord :TEXCOORD0;
	float2 lightmapUV :TEXCOORD1;
	UNITY_VERTEX_INPUT_INSTANCE_ID
};

LitMetaPass.hlsl

struct Attributes
{
	float4 positionOS :POSITION;
	float3 normalOS :NORMAL;
	float2 uv0 :TEXCOORD0;
	float2 uv1 :TEXCOORD1;
	float2 uv2 :TEXCOORD2;
	
	#ifdef _TANGENT_TO_WORLD
	float4 tangentOS :TANGENT;
	#endif
};

URP Lit Shader에서는 LitForwardPass.hlsl이나 GbufferPass.hlsl, LitMetaPass.hlsl등, 각 패스별 hlsl파일에 선언되어 있음.

Vertex Shader to Fragment Shader Stucture (Varying)

Type(s)Name(변경 가능)SemanticNotes
float4posSV_POSITION투영 공간으로 변화된 후의 Vertex Position
float3normalNORMAL뷰 공간으로 변형된 후 Vertex의 Normal값
float4uvTEXCOORD[n]첫 번째 UV 채널 좌표값
float4tangentTANGENTTangent값
float4diff, specCOLORVertex Color 혹은 그 외의 임의의 컬러값
AnyAny사용자 정의Vertex stage에서 계산한 값을 Pixel Shader로 전달할 때 임의로 정의할 수 있음

interpolate(보간기)의 숫자는 Shader Model에 영향을 받는다. Advanced의 #pragma target설정 참고

//Varying Struct는 사용자 정의이므로 임의로 선언할 수 있다.
struct Varying
{
	float4 positionCS :SV_POSITION;
    float2 uc :TEXCOORD0;
};

//Vertex Function(Vertex Shader Stage)
VertexOutput vert(VertexInput v)
{
	VertexOutput o;
    o.vertex = TransformObjectToHClip(v.vertex.xyz);
	return o;
}

Vertex Shader의 주 목적은 3D의 정보를 2D로 변환하는 것.
이를 위해 필요한 정보를 Vertex buffer에서 가져온 값을 사용(VertexInput v), 계산된 결과를 (VertexOutput o)통해 보간기로 Pixel Shader에 전달하게 됨.

위 예제 코드는 Vertex의 포지션 정보만을 계산해 화면에 그리는 간단한 코드

공간 변환(Transform)

3D Mesh의 각 Vertex를 사용하는 툴의 3D 공간으로 변환하는 과정을 거치게 됨.
이 변환 과정은 간략하게 [Object Space]->[World Space]->[Camera Space]->[Clip Space]

월드 변환(Transform Object to World)

Local Space, Objet Space, 물체 공간 모두 다 같은 의미로 오브젝트 별로 가지고 있는 자기만의 공간을 월드 공간내의 좌표로 변환하는 과정

//Core/ShaderLibrary/SpaceTransform.hlsl에서 확인할 수 있음
float4x4 GetObjectToWorldMatrix()
{
	return UNITY_MATRIX_M;
}
...
float3 TransformObjectToWorld(float3 positionOS)
{
	return mul(GetObjectToWorldMatrix(), float(positionOS, 1.0)).xyz;
}
  • 카메라 공간(Transform World to View) : 월드 공간으로 변환된 물체를 카메라의 위치를 기준으로 다시 공간을 변환하는데 이를 카메라 변환이라고 함.
    이때, 카메라의 가시 볼륨 영역에서 near, far에 의해 절단되어 View Frustum(절두체)의 영역으로 다시 정의됨.

0개의 댓글