ゲーム開発カフェ Feelin

Steam公開、東京ゲームショウ2018出展のFeelin Gamesが運営するゲーム開発スクール&カフェ

【Unity】GPU Instancingで、大量の同一オブジェクトを高速描画しよう

ゲームシーンに、沢山のメッシュオブジェクトを配置して、よりリッチな表現にしたい!

でも、トレードオフで、描画速度が遅くなるなぁ。

 

そんなとき、役立つのが、GPU Instancingという機能。

 

この機能を使うと、ゲームシーン内にある、大量の同一オブジェクトを、まとめて描画してくれます。

結果、描画速度のパフォーマンスが上がります。

例えば、草木、石、床板、壁などの複製しているオブジェクトに適用することができます。

 

適用される「同一オブジェクト」の条件とは、同じメッシュMesh、同じマテリアルMaterialであることです。

なお、後述する方法その2で、「同一マテリアルだけれども、色違い」にするということもできます。

 

 

方法その1

マテリアルMaterialのインスペクターにある、Enable GPU Instancingをチェックをオンにします。

f:id:machinelearning:20181110135449j:plain

そして、各々のオブジェクトのマテリアルにセットするだけです。

 

別々のマテリアルをセットした場合、個々に描画されるf:id:machinelearning:20181110135343j:plain

同一マテリアルをセットした場合、まとめて描画される

f:id:machinelearning:20181110135341j:plain

Window > Analysis > Frame Debuggerで上の描画プロセス情報が見れます。

また、スクリプトにてセットする場合は、同一マテリアルを参照したいので、共有マテリアルSharedMaterialの方にセットします。ここがポイント!

NG)GetComponent ().material = マテリアル

OK)GetComponent ().sharedMaterial = マテリアル

 

方法その2

「同一マテリアルだけれども、色違い」にする場合の方法です。

f:id:machinelearning:20181110142618j:plain

 

以下のようなシェーダーファイルを作成します。赤色がGPU Instancing対応するコードです。

Shader "Custom/SurfaceShaderInstanced"
{
    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
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        //fixed4 _Color;

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
            UNITY_DEFINE_INSTANCED_PROP(fixed4, _Color)
        UNITY_INSTANCING_BUFFER_END(Props)

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            // Albedo comes from a texture tinted by color
            //fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

このシェーダーを、作成したマテリアルにセットします。また、Enable GPU Instancingをチェックオン。

f:id:machinelearning:20181110150030j:plain

 

以下スクリプトを作成します。この中で、所望の色をセットしてください。

public class SurfaceShaderInstanced : MonoBehaviour
{
    void Start()
    {
        MaterialPropertyBlock props = new MaterialPropertyBlock();
        props.SetColor("_Color", new Color(Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f)));
        GetComponent<MeshRenderer>().SetPropertyBlock(props);
    }
}

対象のオブジェクトに、スクリプトとマテリアルをセットします。

f:id:machinelearning:20181110150024j:plain

これで、方法その2はOK!

 

ゲームシーンで使っているライティングなどの設定によっては、GPU Instancingの適用条件から外れる場合もあります。

詳細は、Unityのマニュアルサイトを参照ください。

GPU インスタンシング - Unity マニュアル

 

 

GPU Instancingを上手く使って、リッチなゲームシーンを創りましょう!

次のUnity Tips記事の更新をお楽しみに!

ツイート、いいね~よろしく!

 

Yuuki Tsuji @ Feelin Games - The Game Creator

https://twitter.com/Feelin_Games