본 게시물은 Unity Korea 채널의 URP Shader Training 시리즈와 강의에 사용된 도큐먼트를 공부하며 정리한 게시물입니다.
투영 변환(Transform Projection)은 원근법을 구현하기 위해, 카메라 공간에서 정의된 절두체를 축에 나란한 직육면체 볼륨으로 변경하여 카메라 공간의 모든 물체를 3차원 클립 공간으로 변환하는 것.
// Transform to homogenous clip space
// 뷰 공간에서 동차 클립 공간으로 변환하기 위한 Projection Matrix 반환
float4x4 GetViewHClipMatrix()
{
//UNITY_MATRIX_P는 Unity에서 미리 정의된 매크로 -> Projection Matrix를 나타냄
return UNITY_MATRIX_P;
}
// Transform position from view space to homogenous space
// 뷰 공간(View Space)에서 동차 클립 공간(Homogenous Clip)로 위치 변환
float4 TransformWViewToHClip(float3 positionVS)
{
//입력된 위치를 w성분이 1.0인 4차원 벡터로 변환
float4 positionVS4D = float4(positionVS, 1.0);
// Projection Matrix을 사용하여 View Space의 위치를 동차 클립 공간의 위치로 변환
return mul(GetViewHClipMatrix(), positionVS4D);
}
원근 처리를 위해 3차원 공간을 직육면체 볼륨으로 물체들을 변환시키면서 카메라 공간 밖의 Polygon들을 잘라냄(Cliping)
위 코드를 간단하게 정리하면 아래와 같음
// Transform position from object space to homogenous space
float4 TransformObjectToHClip(float3 positionOS)
{
//More efficient than computing M*VP matrix product
return mul(GetWorldToHClipMatrix(), mul(GetObjectToWorldMatrix(), float4(positionOS, 1.0)));
}
위 내용을 풀어서 Vertex Stage에서 계산된 내용을 살펴보면 아래와 같음
VertexOutput vert(VertexInput v)
//VertexInput : Vertex Buffer에서 읽어온 정보 v를 계산에 사용함.
{
VertexOutput o;
//Vertex Stage에서 계산한 결과는 o.를 붙여 보간기를 통해 Pixel Shader로 전달함.
o.vertex = TransformObjectToHClip(v.vertex.xyz);
//Vertex Buffer에서 읽어온 값을 함수에 넣어 계산한 다음, o.vertex를 통해 Pixel Shader로 전달
return o;
}
Pixel로 배열된 Object의 최종 컬러값을 계산하는 단계
half4 frag(VertexOutput i) : SV_Target
// SV_Target -> 이 함수의 반환값은 렌더 타겟에 쓰이는 색상 테이터임을 나타냄.
{
return half4(_TintColor);
}
Properties에 Range 항목을 추가하고, 색 밝기/변경으로 슬라이드로 조절하기
// Shader 시작. 셰이더의 폴더와 이름을 여기서 결정합니다.
Shader "URPTraining/02_Example01"
{
Properties
{
// Properties Block : 셰이더에서 사용할 변수를 선언하고 이를 material inspector에 노출시킵니다
// Color 지정하는 변수를 선언, 변수 타입은 Color이며 기본값은 (1, 1, 1, 1)
_TintColor("Tint Color", Color) = (1, 1, 1, 1)
// 색상의 세기를 최소 0에서 최대 1로 조절하는 변수, 기본값 0.5
_Intensity("Range Sample", Range(0, 1)) = 0.5
}
SubShader
{
Tags
{
//Render type과 Render Queue를 여기서 결정합니다.
"RenderPipeline" = "UniversalPipeline"
"RederType" = "Opaque"
"Queue" = "Geometry"
}
Pass
{
Name "Universal Forward"
Tags { "LightMode" = "UniversalForward"}
HLSLPROGRAM
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma vertex vert
#pragma fragment frag
//cg shader는 .cginc를 hlsl shader는 .hlsl을 include하게 됩니다.
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
float _Intensity;
float4 _TintColor;
//vertex buffer에서 읽어올 정보를 선언합니다.
struct VertexInput
{
float4 vertex : POSITION;
};
//보간기를 통해 버텍스 셰이더에서 픽셀 셰이더로 전달할 정보를 선언합니다.
struct VertexOutput
{
float4 vertex : SV_POSITION;
};
//버텍스 셰이더
VertexOutput vert(VertexInput v)
{
VertexOutput o;
o.vertex = TransformObjectToHClip(v.vertex.xyz);
return o;
}
//픽셀 셰이더
half4 frag(VertexOutput i) : SV_TARGET
{
float4 color = _TintColor * _Intensity;
return color;
}
ENDHLSL
}
}
}