質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

457閲覧

Unity2D GPU Instancing に対応するシェーダ

退会済みユーザー

退会済みユーザー

総合スコア0

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2019/04/25 20:31

前提・実現したいこと

シェーダをGPU Instancingに対応させたい。

該当のソースコード

ShaderLab

1Shader "Unlit/World" 2{ 3 Properties 4 { 5 [NoScaleOffset] _MainTex ("Texture", 2D) = "white" {} 6 7 // 見た目調整用プロパティを変更、前回と異なり大きくするほど鋭くなる 8 [PowerSlider(10)] _EdgeSharpness ("Edge Sharpness", Range(1.0, 100.0)) = 10.0 9 10 _EdgeDist ("Edge Disturbance", Range(0.0, 1.0)) = 0.05 11 _EdgeDistFreq ("Edge Disturbance Frequency", Range(0.0, 16.0)) = 4.0 12 } 13 14 SubShader 15 { 16 Tags { "RenderType"="Opaque" } 17 18 Pass 19 { 20 CGPROGRAM 21 #pragma vertex vert 22 #pragma fragment frag 23 #include "UnityCG.cginc" 24 #pragma multi_compile_instancing // 追加 25 26 // 頂点アトリビュートからはUV関連を削除 27 struct appdata 28 { 29 float4 vertex : POSITION; 30 float4 color : COLOR; 31 UNITY_VERTEX_INPUT_INSTANCE_ID // 追加 32 }; 33 34 // tileUvには(0, 0)、(1, 0)、(0, 1)、(1, 1)のいずれかが入る 35 struct v2f 36 { 37 float4 vertex : SV_POSITION; 38 float2 tileUv : TEXCOORD0; 39 float weight : TEXCOORD1; 40 float2 modelPos : TEXCOORD2; 41 UNITY_VERTEX_INPUT_INSTANCE_ID 42 }; 43 44 inline float random(float2 st) { 45 return frac(sin(dot(st, float2(12.9898, 78.233))) * 43758.5453123); 46 } 47 48 float noise(float2 st) 49 { 50 float2 i = floor(st); 51 float2 f = frac(st); 52 float a = random(i); 53 float b = random(i + float2(1.0, 0.0)); 54 float c = random(i + float2(0.0, 1.0)); 55 float d = random(i + float2(1.0, 1.0)); 56 float2 u = f * f * (3.0 - 2.0 * f); 57 58 return dot(float2(lerp(a, b, u.x), lerp(c - a, d - b, u.x)), float2(1.0, u.y)); 59 } 60 61 float fractal(float2 st) 62 { 63 float4 amp = float4(1.0, 0.5, 0.25, 0.125); 64 float4 v; 65 66 v.x = noise(st); 67 st = st * 2.0 + float2(14.1421356237, 17.3205080757); 68 v.y = noise(st); 69 st = st * 2.0 + float2(22.360679775, 26.4575131106); 70 v.z = noise(st); 71 st = st * 2.0 + float2(31.4159265359, 27.1828182846); 72 v.w = noise(st); 73 74 return dot(v, amp) / dot(1.0, amp); 75 } 76 77 sampler2D _MainTex; 78 float4 _MainTex_ST; 79 float4 _MainTex_TexelSize; 80 float _EdgeSharpness; 81 float _EdgeDist; 82 float _EdgeDistFreq; 83 84 // ユニフォーム変数を追加 85 #define TYPE_COUNT_MAX 8 86 int _TypeCount; 87 float4 _TypeUvs[TYPE_COUNT_MAX / 2]; 88 float2 _TileSize; 89 float _TypeLevels[TYPE_COUNT_MAX]; 90 91 v2f vert(appdata v) 92 { 93 v2f o; 94 o.tileUv = v.color.xy; 95 o.weight = v.color.a; 96 o.modelPos = v.vertex.xy; 97 o.vertex = UnityObjectToClipPos(v.vertex); 98 UNITY_SETUP_INSTANCE_ID(v); // 追加 99 UNITY_TRANSFER_INSTANCE_ID(v, o); 100 101 return o; 102 } 103 104 fixed4 frag(v2f i) : SV_Target 105 { 106 UNITY_SETUP_INSTANCE_ID(i); 107 // まずは前回同様weightを計算する 108 float f = dot(float2(_EdgeDist, 1.0 - _EdgeDist), float2(fractal(i.modelPos * _EdgeDistFreq), 0.5)); 109 float upper = 1.0 - 2.0 * (1.0 - i.weight) * (1.0 - f); 110 float lower = 2.0 * i.weight * f; 111 float weight = lerp(lower, upper, step(0.5, i.weight)); 112 113 // weightを比較してどの範囲にいるか判定し、それを越えない最大のインデックスを調べる 114 uint index = 0; 115 [unroll(TYPE_COUNT_MAX)] 116 for (int k = 0; k < _TypeCount; k++) 117 { 118 if (_TypeLevels[k] < weight) 119 { 120 index = k + 1; 121 continue; 122 } 123 break; 124 } 125 index = min(index, _TypeCount - 1); 126 127 // さらに、その一つ下・一つ上のインデックスを求めておく 128 uint prevIndex = index > 0 ? index - 1 : 0; 129 uint nextIndex = min(index + 1, _TypeCount - 1); 130 131 // 範囲の下限・上限の高さを取得し、lowerLevelを0、upperLevelを1としたときのweightの位置を調べる 132 float lowerLevel = (index == prevIndex) ? 0.0 : _TypeLevels[prevIndex]; 133 float upperLevel = (index == nextIndex) ? 1.0 : _TypeLevels[index]; 134 float weightInRange = (lowerLevel == upperLevel) ? 0.0 : (weight - lowerLevel) / (upperLevel - lowerLevel); 135 136 // weightInRangeが0.5以上かどうかでnextIndex、prevIndexのいずれかを選択する 137 uint edgeIndex = weightInRange >= 0.5 ? nextIndex : prevIndex; 138 139 // weightInRangeが0.5の時0、そこより範囲境界に近いほど1になるような値を作る 140 // このとき_EdgeSharpness乗して、カーブを適宜鋭くする 141 float edgeFactor = saturate(pow(abs(weightInRange * 2.0 - 1.0), _EdgeSharpness)); 142 143 // 範囲中心および範囲境界に対応するUVを取得し、そこからそれぞれ色を取得する 144 float4 edgeVector = _TypeUvs[edgeIndex / 2]; 145 float4 centerVector = _TypeUvs[index / 2]; 146 float2 edgeUv = lerp(edgeVector.xy, edgeVector.zw, edgeIndex % 2); 147 float2 centerUv = lerp(centerVector.xy, centerVector.zw, index % 2); 148 float2 uvOffset = i.tileUv * _TileSize; 149 fixed4 edgeColor = tex2D(_MainTex, edgeUv + uvOffset); 150 fixed4 centerColor = tex2D(_MainTex, centerUv + uvOffset); 151 152 // 範囲中心でcenterColorが100%、境界部分でcenterColorとedgeColorが 153 // 50%混合になるように2つの色を混ぜ合わせる 154 return lerp(centerColor, edgeColor, edgeFactor * 0.5); 155 } 156 ENDCG 157 } 158 } 159}

試したこと

(http://tips.hecomi.com/entry/2018/09/24/232125)

↑のHPを参考に、マテリアルの設定から「enable gpu instancing」が表示出来るようにはしたのですが、実際にプレイしてみると、描画されていませんでした。シェーダのことをよく分からないため、どう直せばいいのかが分かりません。GPU Instancing に対応させる方法を教えていただけるとありがたいです。

回答お願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ご提示いただいたUnity の GPU Instancing に対応するシェーダのコードを調べてみた - 凹みTips記事中の「頂点シェーダ」の節をご覧いただきたいのですが、UNITY_SETUP_INSTANCE_ID(v)vertの頭の方に配置されています。
記事によれば、インスタンシング版のコードではUnityObjectToClipPosの内部でunity_InstanceIDを使用するとのことですので、それを設定するためのUNITY_SETUP_INSTANCE_IDマクロはそこよりも手前の位置に移動するべきかと思います。

ShaderLab

1 // 省略 2 3 v2f vert(appdata v) 4 { 5 v2f o; 6 UNITY_SETUP_INSTANCE_ID(v); // IDセットアップをUnityObjectToClipPos使用部分よりも手前に移動 7 o.tileUv = v.color.xy; 8 o.weight = v.color.a; 9 o.modelPos = v.vertex.xy; 10 o.vertex = UnityObjectToClipPos(v.vertex); 11 UNITY_TRANSFER_INSTANCE_ID(v, o); 12 13 return o; 14 } 15 16 // 省略

投稿2019/04/26 06:44

Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/04/27 11:42

回答ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問