Version: 2022.3
언어: 한국어
빌트인 셰이더 변수
샘플러 상태 사용

셰이더 데이터 타입 및 정밀도

Unity는 스탠다드 셰이더 언어 HLSL을 사용하며 일반 HLSL 데이터 타입을 지원합니다.하지만 Unity는 일부 데이터 타입을 HLSL과 다르게 처리하여 모바일 플랫폼에서 더 향상된 지원을 제공합니다.

기본 데이터 타입

셰이더는 부동 소수점 숫자(C#과 같은 일반 프로그래밍 언어에서는 float라고도 함)를 사용하여 대부분의 계산을 수행합니다.Unity의 HLSL 구현에서 스칼라 부동 소수점 데이터 타입은 float, half, fixed입니다.이러한 데이터 타입은 정밀도가 다르기 때문에 성능이나 전력 사용량도 다릅니다.또한 벡터 및 매트릭스에는 half3float4x4와 같은 여러 관련 데이터 타입이 있습니다.

고정밀도: float

이는 정밀도가 가장 높은 부동 소수점 데이터 타입입니다.대부분의 플랫폼에서 float 값은 일반 프로그래밍 언어에서와 같이 32비트입니다.

전체 float 정밀도는 일반적으로 월드 공간 포지션, 텍스처 좌표 또는 삼각법이나 제곱/지수연산 같은 복합 함수를 수반하는 스칼라 계산에 유용합니다.이러한 목적으로 정밀도가 낮은 부동 소수점 데이터 타입을 사용하는 경우 정밀도 관련 아티팩트가 발생할 수 있습니다.예를 들어 텍스처 좌표의 경우, half는 큰 텍스처의 1 텍셀 오프셋을 정확하게 나타내기에 정밀도가 충분하지 않습니다.

중정밀도: half

이는 정밀도가 중간 정도인 부동 소수점 데이터 타입입니다.half 값을 지원하는 플랫폼에서는 일반적으로 16비트입니다.다른 플랫폼에서는 float가 됩니다.

half 값은 float 값보다 범위가 더 작고 정밀도가 더 낮습니다.

반정밀도는 짧은 벡터, 방향, 오브젝트 공간 포지션, 높은 동적 범위 컬러와 같이 높은 정밀도가 필요하지 않은 값의 셰이더 성능을 향상시키는 데 유용합니다.

저정밀도: fixed

이는 OpenGL ES 2.0 Graphics API에서만 지원됩니다.다른 API에서는 지원되는 정밀도가 가장 낮아집니다(half 또는 float).

정밀도가 가장 낮은 고정 포인트 값이며 일반적으로 11비트입니다.fixed 값의 범위는 –2.0에서 +2.0이며 정밀도는 1/256입니다.

고정 정밀도는 보통 일반 텍스처에 저장되는 일반 컬러와 간단한 컬러 작업 수행에 유용합니다.

부동 소수점 숫자

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);

부동 소수점 숫자

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는 선택한 플랫폼에 따라 정수 타입을 지원하지 않을 수 있습니다.예를 들어 OpenGL ES 2.0 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 변환 매트릭스입니다.하지만 OpenGL ES 2.0 같은 일부 플랫폼에서는 정사각형 매트릭스만 지원합니다.

텍스처/샘플러 타입

일반적으로 텍스처를 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;

정밀도, 하드웨어 지원 및 성능

PC(Windows/Mac/Linu) GPU는 항상 고정밀도이기 때문에 셰이더에서 float, half, fixed 중 어느 데이터 타입을 작성하든 상관없습니다.항상 모든 것을 전체 32비트 부동 소수점 정밀도로 계산합니다.

halffixed 타입은 모바일 GPU가 타겟인 경우에만 중요합니다. 이 경우 두 타입은 주로 전력 및 성능 제약을 위해 존재합니다.모바일에서 셰이더를 테스트하여 정밀도/숫자 문제가 발생하지 않는지 확인해야 합니다.

모바일 GPU의 경우에도 여러 정밀도 지원이 GPU 제품군에 따라 다릅니다. 다음은 각 모바일 GPU 제품군이 각 플로팅 포인트 타입(각 타입에 사용된 비트 수로 나타냄)을 처리하는 방법의 개요입니다.

GPU 제품 float half fixed
PowerVR Series 6/7 32 16
PowerVR SGX 5xx 32 16 11
Qualcomm Adreno 4xx/3xx 32 16
Qualcomm Adreno 2xx 32버텍스 24프래그먼트
ARM Mali T6xx/7xx 32 16
ARM Mali 400/450 32버텍스 16프래그먼트
NVIDIA X1 32 16
NVIDIA K1 32
NVIDIA Tegra 3/4 32 16

대부분의 최신 모바일 GPU는 실제로 32비트 숫자(float 타입에 사용됨) 또는 16비트 숫자(halffixed 타입에 모두 사용됨) 중 하나만 지원합니다. 일부 구형 GPU의 버텍스 셰이더 및 프래그먼트 셰이더 연산 정밀도는 다릅니다.

더 낮은 정밀도를 사용하면 GPU 레지스터 할당 개선으로 인해 또는 특정 저정밀도 수학 연산을 위한 특수 “빠른 경로” 실행 유닛으로 인해 종종 빨라질 수 있습니다. 순수한 성능상의 이점이 없는 경우에도 더 낮은 정밀도를 사용하면 종종 GPU에 전원이 덜 사용되어 배터리 수명이 연장됩니다.

Unity는 포지션 및 텍스처 좌표를 제외한 모든 것에 대해 반정밀도로 시작할 것을 권장합니다.계산의 일부분에 반정밀도가 충분하지 않은 경우에만 정밀도를 높여야 합니다.

무한, NaN 및 기타 특수 플로팅 포인트 값에 대한 지원

특수 부동 소수점 값에 대한 지원은 사용하는 GPU 제품군(대부분 모바일)에 따라 다를 수 있습니다.

Direct3D 10을 지원하는 모든 PC GPU는 매우 정확하게 규정된 IEEE 754 부동 소수점 스탠다드를 지원합니다.즉 부동 소수점은 CPU에 일반적인 프로그래밍 언어에서 동작하는 것과 똑같이 동작합니다.

모바일 GPU의 지원 수준은 약간 다를 수 있습니다.일부 GPU에서 0을 0으로 나눈 결과는 NaN(“숫자 아님”)이 될 수 있고, 그 외의 GPU에서는 무한대, 0, 또는 기타 지정되지 않은 값이 될 수 있습니다.타겟 디바이스에서 셰이더를 테스트하여 지원되는지 확인해야 합니다.

외부 GPU 문서

GPU 제조사는 자사 GPU의 성능 및 기능에 대한 심층적인 가이드를 제공합니다. 자세한 내용은 다음을 참조하십시오.

추가 리소스:

빌트인 셰이더 변수
샘플러 상태 사용