이 페이지는 커스텀 Unity 셰이더에 GPU 인스턴싱 지원을 추가하는 방법에 대한 정보를 포함하고 있습니다. 먼저 커스텀 Unity 셰이더가 GPU 인스턴싱을 지원하는 데 필요한 셰이더 키워드, 변수 및 함수에 대해 설명합니다. 그런 다음 표면 셰이더와 버텍스/프래그먼트 셰이더 모두에 인스턴스당 데이터를 추가하는 방법을 다룬 예제를 포함합니다.
기능 | 빌트인 렌더 파이프라인 | 유니버설 렌더 파이프라인(URP) | 고해상도 렌더 파이프라인(HDRP) | 커스텀 스크립터블 렌더 파이프라인(SRP) |
---|---|---|---|---|
커스텀 GPU 인스턴스화된 셰이더 | 지원 | 지원 안 함 | 지원 안 함 | 지원 안 함 |
이 섹션은 GPU 인스턴싱과 관련된 셰이더 추가에 대한 정보를 포함하고 있습니다.
덧셈 | 설명 |
---|---|
#pragma multi_compile_instancing |
인스턴싱 배리언트를 생성합니다. 이것은 프래그먼트 및 버텍스 셰이더에 필요합니다. 표면 셰이더에서는 선택 사항입니다. |
#pragma instancing_options
|
Unity가 인스턴스에 사용하는 옵션을 지정합니다.사용 가능한 옵션 스위치에 대한 자세한 내용은 #pragma instancing_options 를 참조하십시오. |
UNITY_VERTEX_INPUT_INSTANCE_ID |
버텍스 셰이더 입출력 구조에서 인스턴스 ID를 정의합니다. 이 매크로를 사용하려면 INSTNCING_ON 셰이더 키워드를 활성화하십시오. 그렇지 않으면 Unity가 인스턴스 ID를 설정하지 않습니다. 인스턴스 ID에 액세스하려면 #ifdef INSTANCING_ON 블록 내에서 vertexInput.instanceID 를 사용합니다. 이 블록을 사용하지 않으면 배리언트가 컴파일되지 않습니다. |
UNITY_INSTANCING_BUFFER_START(bufferName) |
bufferName 이라는 인스턴스당 상수 버퍼의 시작을 선언합니다. 이 매크로를 UNITY_INSTNCING_BUFFER_END 와 함께 사용하여 각 인스턴스에 고유하게 하려는 프로퍼티 선언을 래핑합니다. UNITY_DEFINE_INSTANCED_PROP 를 사용하여 버퍼 내부의 프로퍼티를 선언합니다. |
UNITY_INSTANCING_BUFFER_END(bufferName) |
bufferName 이라는 인스턴스당 상수 버퍼의 끝을 선언합니다. 이 매크로를 UNITY_INSTNCING_BUFFER_START 와 함께 사용하여 각 인스턴스에 고유하게 하려는 프로퍼티 선언을 래핑합니다. UNITY_DEFINE_INSTANCED_PROP 를 사용하여 버퍼 내부의 프로퍼티를 선언합니다. |
UNITY_DEFINE_INSTANCED_PROP(type, propertyName) |
지정된 타입과 이름을 사용하여 인스턴스당 셰이더 프로퍼티를 정의합니다. 아래 예제에서 _Color 프로퍼티는 고유합니다. |
UNITY_SETUP_INSTANCE_ID(v); |
셰이더 함수가 인스턴스 ID에 액세스할 수 있도록 합니다. 버텍스 셰이더의 경우 이 매크로를 처음에 사용해야 합니다. 프래그먼트 셰이더의 경우 이 추가는 선택 사항입니다. 예를 들어 버텍스 및 프래그먼트 셰이더를 참조하십시오. |
UNITY_TRANSFER_INSTANCE_ID(v, o); |
버텍스 셰이더의 입력 구조에서 출력 구조로 인스턴스 ID를 복사합니다. 프래그먼트 셰이더에서 인스턴스당 데이터에 액세스해야 하는 경우 이 매크로를 사용합니다. |
UNITY_ACCESS_INSTANCED_PROP(bufferName, propertyName) |
인스턴스 상수 버퍼의 인스턴스당 셰이더 프로퍼티에 액세스합니다. Unity는 인스턴스 ID를 사용하여 인스턴스 데이터 배열을 인덱싱합니다. bufferName 은 지정된 프로퍼티를 포함하는 상수 버퍼의 이름과 일치해야 합니다. 이 매크로는 INSTNCING_ON 및 인스턴싱되지 않은 배리언트에 대해 다르게 컴파일합니다. |
여러 개의 인스턴스당 프로퍼티를 사용하는 경우 MaterialPropertyBlock
오브젝트에서 모든 프로퍼티를 채울 필요는 없습니다. 또한 한 인스턴스에 프로퍼티가 없는 경우 Unity는 참조된 머티리얼에서 기본값을 가져옵니다. 머티리얼에 프로퍼티에 대한 기본값이 없는 경우 Unity는 해당 값을 0으로 설정합니다. 인스턴싱이 비활성화되기 때문에 MaterialPropertyBlock
에 인스턴스화가 안된 프로퍼티를 두면 안 됩니다. 대신 다른 머티리얼을 만들어야 합니다.
[#pragma instancing_options](#pragma-instancing_options) 지시문에서는 다음의 스위치를 사용할 수 있습니다.
스위치 | 설명 |
---|---|
forcemaxcount:batchSize 와 maxcount:batchSize
|
대부분의 플랫폼에서 Unity는 인스턴싱 데이터 배열 크기를 자동으로 계산합니다.타겟 디바이스의 최대 상수 버퍼 크기를 모든 인스턴스당 프로퍼티를 포함하는 구조의 크기로 나눕니다.일반적으로 배치 크기에 대해 걱정할 필요가 없습니다.그러나 일부 플랫폼에는 고정된 배열 크기가 필요합니다. 해당 플랫폼의 배치 크기를 지정하기 위해서는 maxcount 옵션을 사용합니다.다른 플랫폼은 이 옵션을 무시합니다.모든 플랫폼에 배치 크기를 강제로 적용하려면 forcemaxcount 를 사용합니다.이는 프로젝트에서 RenderMeshInstanced를 사용하여 256개의 인스턴스화된 스프라이트가 있는 드로우 콜을 실행할 때 유용합니다.두 옵션의 기본값은 500입니다. |
assumeuniformscaling |
모든 인스턴스의 스케일링이 동일하다고 가정하도록 Unity에 지시합니다(모든 X, Y 및 Z축에 대한 동일한 스케일). |
nolodfade |
Unity가 LOD 페이드 값에 GPU 인스턴싱을 적용하지 않도록 합니다. |
nolightprobe |
Unity가 라이트 프로브 값과 해당 오클루전 데이터에 GPU 인스턴싱을 적용하지 못하도록 합니다. 프로젝트에 GPU 인스턴싱과 라이트 프로브를 모두 사용하는 게임 오브젝트가 포함되어 있지 않은 경우 이 옵션을 ON 으로 설정하면 퍼포먼스가 향상될 수 있습니다. |
nolightmap |
Unity가 GPU 인스턴싱을 라이트맵 아틀라스 정보 값에 적용하지 못하도록 합니다. 프로젝트에 GPU 인스턴싱과 라이트맵을 모두 사용하는 게임 오브젝트가 포함되어 있지 않은 경우 이 옵션을 ON 으로 설정하면 성능이 향상될 수 있습니다. |
procedural:FunctionName |
Graphics.RenderMeshIndirect와 함께 사용할 추가 배리언트를 생성합니다.버텍스 셰이더 시작 단계에서 Unity가 콜론 다음에 지정되는 함수를 호출합니다.인스턴스 데이터를 수동으로 설정하려면 일반적으로 인스턴스당 데이터를 셰이더에 추가하는 방식과 동일한 방식으로 인스턴스당 데이터를 이 함수에 추가합니다.또한 가져온 인스턴스 프로퍼티 중 프래그먼트 셰이더에 포함된 프로퍼티가 있을 경우 Unity는 프래그먼트 셰이더 시작 단계에서 이 함수를 호출합니다. |
Unity는 #pragma
지시문에서 noinstancing
을 지정하지 않는 한 기본적으로 인스턴싱 배리언트를 사용하여 표면 셰이더를 생성합니다. Unity는 표면 셰이더에서 #pragma multi_compile_instancing 사용을 무시합니다.
Unity의 스탠다드 및 스탠다드 스페큘러 셰이더는 기본적으로 인스턴싱을 지원하지만 변환 외에는 인스턴스당 프로퍼티가 없습니다.
씬에 GPU 인스턴싱이 활성화된 게임 오브젝트가 포함되어 있지 않으면 Unity는 인스턴싱 셰이더 배리언트를 제거합니다. 스트립 동작을 오버라이드하려면 다음 단계를 따르십시오.
기본적으로 Unity GPU는 인스턴스화된 각 드로우 콜에서 서로 다른 트랜스폼이 있는 게임 오브젝트를 인스턴스화합니다. 인스턴스에 더 많은 배리에이션을 추가하려면 셰이더를 수정하여 컬러와 같은 인스턴스당 프로퍼티를 추가합니다. 표면 셰이더와 버텍스/프래그먼트 셰이더 모두에서 이 작업을 수행할 수 있습니다.
커스텀 셰이더는 인스턴스당 데이터가 필요하지 않지만 인스턴스 ID가 필요합니다. 월드 매트릭스가 올바르게 작동하려면 인스턴스 ID가 필요하기 때문입니다. 표면 셰이더는 자동으로 인스턴스 ID를 설정하지만 커스텀 버텍스와 프래그먼트 셰이더는 그렇지 않습니다. 커스텀 버텍스와 프래그먼트 셰이더의 ID를 설정하려면 셰이더 시작 부분에 UNITY_SETUP_INSTANCE_ID를 사용합니다. 이를 수행하는 방법의 예는 버텍스 및 프래그먼트 셰이더를 참조하십시오.
인스턴스 프로퍼티를 선언하면 Unity는 게임 오브젝트에 설정된 MaterialPropertyBlock 오브젝트의 모든 프로퍼티 값을 하나의 드로우 콜로 수집합니다. MaterialPropertyBlock 오브젝트를 사용하여 런타임 시 인스턴스당 데이터를 설정하는 방법의 예는 런타임 시 인스턴스당 데이터 변경을 참조하십시오.
멀티 패스 셰이더에 인스턴스당 데이터를 추가할 때 다음 사항에 유의하십시오.
다음 예에서는 각 인스턴스에 다른 컬러 값을 가지는 인스턴스화된 표면 셰이더를 생성하는 방법을 보여줍니다.
Shader "Custom/InstancedColorSurfaceShader"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Uses the physically based standard lighting model with shadows enabled for all light types.
#pragma surface surf Standard fullforwardshadows
// Use Shader model 3.0 target
#pragma target 3.0
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_DEFINE_INSTANCED_PROP(fixed4, _Color)
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o) {
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
o.Albedo = c.rgb;
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
다음 예에서는 각 인스턴스에 다른 컬러 값을 가지는 인스턴스화된 버텍스 및 프래그먼트 셰이더를 생성하는 방법을 보여줍니다. 표면 셰이더와 달리 버텍스 및 프래그먼트 셰이더를 생성할 때 UNITY_SETUP_INSTANCE_ID를 사용하여 인스턴스 ID를 수동으로 설정해야 합니다.
Shader "Custom/SimplestInstancedShader"
{
Properties
{
_Color ("Color", Color) = (1, 1, 1, 1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID // use this to access instanced properties in the fragment shader.
};
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
UNITY_INSTANCING_BUFFER_END(Props)
v2f vert(appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o);
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(i);
return UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
}
ENDCG
}
}
}
다음 예에서는 MaterialPropertyBlock 오브젝트를 사용하여 런타임 시 게임 오브젝트 그룹에 대한 인스턴스당 데이터를 설정하는 방법을 보여줍니다. 위의 셰이더 예제에서 _Color
프로퍼티를 랜덤 컬러로 설정합니다.
중요: MaterialPropertyBlocks는 SRP 배처 호환성을 차단합니다. 자세한 내용은 GPU 인스턴싱: 요구 사항 및 호환성을 참조하십시오.
using UnityEngine;
public class MaterialPropertyBlockExample : MonoBehaviour
{
public GameObject[] objects;
void Start()
{
MaterialPropertyBlock props = new MaterialPropertyBlock();
MeshRenderer renderer;
foreach (GameObject obj in objects)
{
float r = Random.Range(0.0f, 1.0f);
float g = Random.Range(0.0f, 1.0f);
float b = Random.Range(0.0f, 1.0f);
props.SetColor("_Color", new Color(r, g, b));
renderer = obj.GetComponent<MeshRenderer>();
renderer.SetPropertyBlock(props);
}
}
}
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.