Unity는 스탠다드 셰이더 언어 HLSL을 사용하며 일반 HLSL 데이터 타입을 지원합니다.하지만 Unity는 일부 데이터 타입을 HLSL과 다르게 처리하여 모바일 플랫폼에서 더 향상된 지원을 제공합니다.
셰이더는 대부분 부동 소수점 숫자(C#과 같은 일반 프로그래밍 언어에서는 float
라고도 함)를 사용하여 계산합니다. Unity의 HLSL 구현에서 스칼라 부동 소수점 데이터 타입은 float
와 half
입니다. 이러한 데이터 타입은 정밀도가 다르기 때문에 성능 또는 전력 사용량도 달라집니다. half3
, float4x4
와 같이 벡터 및 매트릭스와 관련된 데이터 타입도 여러 가지 있습니다.
float
이는 정밀도가 가장 높은 부동 소수점 데이터 타입입니다.대부분의 플랫폼에서 float
값은 일반 프로그래밍 언어에서와 같이 32비트입니다.
전체 float
정밀도는 일반적으로 월드 공간 포지션, 텍스처 좌표 또는 삼각법이나 제곱/지수연산 같은 복합 함수를 수반하는 스칼라 계산에 유용합니다.이러한 목적으로 정밀도가 낮은 부동 소수점 데이터 타입을 사용하는 경우 정밀도 관련 아티팩트가 발생할 수 있습니다.예를 들어 텍스처 좌표의 경우, half
는 큰 텍스처의 1 텍셀 오프셋을 정확하게 나타내기에 정밀도가 충분하지 않습니다.
half
이는 정밀도가 중간 정도인 부동 소수점 데이터 타입입니다.half
값을 지원하는 플랫폼에서는 일반적으로 16비트입니다.다른 플랫폼에서는 float
가 됩니다.
half
값은 float
값보다 범위가 더 작고 정밀도가 더 낮습니다.
반정밀도는 짧은 벡터, 방향, 오브젝트 공간 포지션, 높은 동적 범위 컬러와 같이 높은 정밀도가 필요하지 않은 값의 셰이더 성능을 향상시키는 데 유용합니다.
Unity의 셰이더 컴파일러는 HLSL의 부동 소수점 숫자 접미사를 무시합니다.따라서 접미사가 있는 부동 소수점 숫자는 모두 float
가 됩니다.
다음 코드는 Unity에서 접미사 h
가 있는 숫자가 부정적인 영향을 미칠 수 있음을 보여줍니다.
half3 packedNormal = ...;
half3 normal = packedNormal * 2.0h - 1.0h;
접미사 h
가 무시되기 때문에 셰이더 컴파일러는 다음 단계를 실행하는 코드를 생성합니다.
1. 중간 normal
값을 고정밀도로 계산합니다(float3
).
2. 중간 값을 half3
로 전환합니다.
이렇게 하면 셰이더의 성능이 감소합니다.
다음 코드는 계산에 half
값만 사용하기 때문에 더욱 효율적입니다.
half3 packedNormal = ...;
half3 normal = packedNormal * half(2.0) - half(1.0);
정수(int
데이터 타입)는 종종 루프 카운터나 배열 인덱스로 사용되며 일반적으로 다양한 플랫폼에서 문제 없이 사용 가능합니다.
선택한 플랫폼에 따라서 GPU가 정수 타입을 지원하지 않을 수 있습니다.
Direct3D 11, OpenGL ES 3, Metal, 기타 최신 플랫폼은 정수 데이터 타입을 제대로 지원하므로 비트 시프트와 비트 마스킹을 사용하면 올바르게 작동합니다.
HLSL에는 기본 타입을 토대로 만든 빌트인 벡터 및 매트릭스 타입이 있습니다.예를 들어, float3
는 .x, .y, .z 컴포넌트가 있는 3D 벡터이며 half4
는 .x, .y, .z, .w 컴포넌트가 있는 중정밀도 4D 벡터입니다.또는 컬러 관련 작업을 수행할 때 유용한 .r, .g, .b, .a 컴포넌트를 사용하여 벡터를 인덱싱할 수 있습니다.예시:
float4 myColor = ...
float redValue = myColor.r;
매트릭스 타입도 유사한 방법으로 빌드됩니다. 예를 들어 float4x4
는 4x4 변환 매트릭스입니다. 그러나 일부 플랫폼에서는 정사각형 매트릭스만 지원합니다.
일반적으로 텍스처를 HLSL 코드에서 다음 방법으로 선언합니다.
sampler2D _MainTex;
samplerCUBE _Cubemap;
모바일 플랫폼의 경우 low precision samplers
로 변환됩니다. 즉, 텍스처에는 저정밀도 데이터가 있어야 합니다.
Shader precision model 드롭다운을 사용하여 플레이어 설정에서 Unity 프로젝트 전체의 기본 샘플러 정밀도를 변경할 수 있습니다.
텍스처에 HDR 컬러가 포함되어 있음을 알고 있는 경우 반정밀도 샘플러를 사용할 수 있습니다.
sampler2D_half _MainTex;
samplerCUBE_half _Cubemap;
또는 텍스처에 전체 플로트 정밀도 데이터 뎁스 텍스처가 포함된 경우, 전체 정밀도 샘플러를 사용합니다.
sampler2D_float _MainTex;
samplerCUBE_float _Cubemap;
데스크톱 플랫폼 및 대부분의 최신 모바일 플랫폼의 GPU는 버텍스 및 프래그먼트 셰이더 단계에서 32비트 부동 소수점 정밀도를 지원합니다. 그러나 모바일 GPU는 낮은 정밀도를 사용하면 성능이 향상되고 에너지 효율이 높아집니다.
플랫폼에서 낮은 정밀도를 지원하는 경우 half
를 사용하면 다음과 같은 효과가 있습니다.
월드 공간 좌표와 텍스처 좌표를 제외한 모든 것에 대해 낮은 정밀도로 시작해야 합니다. 낮은 정밀도를 사용하면 셰이더 계산에 눈에 보이는 오류(예: 컬러 밴드 또는 위치 간에 이동하는 지오메트리)가 발생하는지 확인합니다. 오류가 발생하는 경우 정밀도를 높입니다.
특수 부동 소수점 값에 대한 지원은 사용하는 GPU 제품군(대부분 모바일)에 따라 다를 수 있습니다.
Direct3D 10을 지원하는 모든 PC GPU는 매우 정확하게 규정된 IEEE 754 부동 소수점 스탠다드를 지원합니다.즉 부동 소수점은 CPU에 일반적인 프로그래밍 언어에서 동작하는 것과 똑같이 동작합니다.
모바일 GPU의 지원 수준은 약간 다를 수 있습니다.일부 GPU에서 0을 0으로 나눈 결과는 NaN(“숫자 아님”)이 될 수 있고, 그 외의 GPU에서는 무한대, 0, 또는 기타 지정되지 않은 값이 될 수 있습니다.타겟 디바이스에서 셰이더를 테스트하여 지원되는지 확인해야 합니다.
GPU 제조사는 자사 GPU의 성능 및 기능에 대한 심층적인 가이드를 제공합니다. 자세한 내용은 다음을 참조하십시오.