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

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

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

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

3DCG

コンピュータの演算により、3次元空間の仮想物体を、2次元平面上で表現する手法である。

Q&A

解決済

1回答

2323閲覧

unity:sharedMaterialのシェーダー内に条件分岐を仕込む

vinvinvidal

総合スコア18

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

3DCG

コンピュータの演算により、3次元空間の仮想物体を、2次元平面上で表現する手法である。

0グッド

0クリップ

投稿2020/10/04 00:02

お世話になっております。
unityのsharedMaterialに関しまして。
頂点カラー以外でフラグメントシェーダー内の条件分岐に利用できる値といえば何がありますでしょうか。

ドローコールを減らすためにsharedMaterialを採用しているのですが、
メッシュ別の表現に幅を持たせるため、フラグメントシェーダー内に条件分岐を仕込みたいと考えました。

現在は、頂点カラーのRGBをシェーダー内で色相彩度輝度の調整に使い、
頂点カラーのアルファを人物、建物などの判定に使い、上手くいっております。

もっと作りこめばさらに拡張できそうなので頑張りたいと思っています。
頂点カラー以外でsharedMaterialのシェーダー内条件分岐に利用できる値と言えば他に何がありますでしょうか。

ご教示のほど、よろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

その他のデータの埋め込み先となると、やはりテクスチャ座標でしょうかね。
UVの働きを検証する – Tsumiki Tech Times|積木製作などのサイトでも触れられているように、一部のテクスチャ座標はGIだとかのために使われる場合があるため要注意でしょうが、気をつけて使えば役に立つかと思います。
データをセットする際にも、uvuv2uv3...だとVector2しか受け付けてくれませんが、SetUVsならVector4までセットすることが可能ですので、けっこういろんなデータを送り込む余地があるでしょう。

試しに下記のようなスクリプトでメッシュを作ったところ...

C#

1using System.Linq; 2using UnityEngine; 3 4[RequireComponent(typeof(MeshFilter))] 5public class UVTest : MonoBehaviour 6{ 7 private void Start() 8 { 9 var vertices = new[] 10 { 11 new Vector3(-0.5f, -0.5f, 0.0f), 12 new Vector3(0.5f, -0.5f, 0.0f), 13 new Vector3(-0.5f, 0.5f, 0.0f), 14 new Vector3(0.5f, 0.5f, 0.0f) 15 }; 16 var uv0 = new[] 17 { 18 new Vector4(0.0f, 0.0f, 0.25f, 0.0f), 19 new Vector4(0.25f, 0.0f, 0.5f, 0.0f), 20 new Vector4(0.0f, 0.25f, 0.25f, 0.25f), 21 new Vector4(0.25f, 0.25f, 0.5f, 0.25f) 22 }; 23 var uv1 = uv0.Select(uv => uv + new Vector4(0.5f, 0.0f, 0.5f, 0.0f)).ToArray(); 24 var uv2 = uv0.Select(uv => uv + new Vector4(0.0f, 0.25f, 0.0f, 0.25f)).ToArray(); 25 var uv3 = uv1.Select(uv => uv + new Vector4(0.0f, 0.25f, 0.0f, 0.25f)).ToArray(); 26 var uv4 = uv2.Select(uv => uv + new Vector4(0.0f, 0.25f, 0.0f, 0.25f)).ToArray(); 27 var uv5 = uv3.Select(uv => uv + new Vector4(0.0f, 0.25f, 0.0f, 0.25f)).ToArray(); 28 var uv6 = uv4.Select(uv => uv + new Vector4(0.0f, 0.25f, 0.0f, 0.25f)).ToArray(); 29 var uv7 = uv5.Select(uv => uv + new Vector4(0.0f, 0.25f, 0.0f, 0.25f)).ToArray(); 30 var indices = new[] 31 { 32 0, 2, 1, 3, 1, 2 33 }; 34 var mesh = new Mesh 35 { 36 name = "UV Test", 37 vertices = vertices 38 }; 39 mesh.SetUVs(0, uv0); 40 mesh.SetUVs(1, uv1); 41 mesh.SetUVs(2, uv2); 42 mesh.SetUVs(3, uv3); 43 mesh.SetUVs(4, uv4); 44 mesh.SetUVs(5, uv5); 45 mesh.SetUVs(6, uv6); 46 mesh.SetUVs(7, uv7); 47 mesh.triangles = indices; 48 mesh.RecalculateBounds(); 49 this.GetComponent<MeshFilter>().sharedMesh = mesh; 50 } 51}

インスペクター上のプレビュー欄には8個のUV座標を持っている様子が表示されました。

図1

マテリアルを下記のようにして...

ShaderLab

1Shader "Unlit/UVTest" 2{ 3 Properties 4 { 5 _MainTex ("Texture", 2D) = "white" {} 6 } 7 SubShader 8 { 9 Tags { "Queue"="Transparent" "RenderType"="Transparent" } 10 11 Pass 12 { 13 Blend SrcAlpha OneMinusSrcAlpha 14 15 CGPROGRAM 16 #pragma vertex vert 17 #pragma fragment frag 18 19 #include "UnityCG.cginc" 20 21 struct appdata 22 { 23 float4 vertex : POSITION; 24 float4 uv0 : TEXCOORD0; 25 float4 uv1 : TEXCOORD1; 26 float4 uv2 : TEXCOORD2; 27 float4 uv3 : TEXCOORD3; 28 float4 uv4 : TEXCOORD4; 29 float4 uv5 : TEXCOORD5; 30 float4 uv6 : TEXCOORD6; 31 float4 uv7 : TEXCOORD7; 32 }; 33 34 struct v2f 35 { 36 float2 uv : TEXCOORD0; 37 float4 vertex : SV_POSITION; 38 }; 39 40 sampler2D _MainTex; 41 42 v2f vert (appdata v) 43 { 44 v2f o; 45 o.vertex = UnityObjectToClipPos(v.vertex); 46 switch (uint(_Time.y) % 16) 47 { 48 default: 49 o.uv = v.uv0.xy; 50 break; 51 case 1: 52 o.uv = v.uv0.zw; 53 break; 54 case 2: 55 o.uv = v.uv1.xy; 56 break; 57 case 3: 58 o.uv = v.uv1.zw; 59 break; 60 case 4: 61 o.uv = v.uv2.xy; 62 break; 63 case 5: 64 o.uv = v.uv2.zw; 65 break; 66 case 6: 67 o.uv = v.uv3.xy; 68 break; 69 case 7: 70 o.uv = v.uv3.zw; 71 break; 72 case 8: 73 o.uv = v.uv4.xy; 74 break; 75 case 9: 76 o.uv = v.uv4.zw; 77 break; 78 case 10: 79 o.uv = v.uv5.xy; 80 break; 81 case 11: 82 o.uv = v.uv5.zw; 83 break; 84 case 12: 85 o.uv = v.uv6.xy; 86 break; 87 case 13: 88 o.uv = v.uv6.zw; 89 break; 90 case 14: 91 o.uv = v.uv7.xy; 92 break; 93 case 15: 94 o.uv = v.uv7.zw; 95 break; 96 } 97 return o; 98 } 99 100 fixed4 frag (v2f i) : SV_Target 101 { 102 return tex2D(_MainTex, i.uv); 103 } 104 ENDCG 105 } 106 } 107}

TextMesh Proに付属していた下図テクスチャを割り当てたところ...

図2

下図のように1秒ごとに16種類の顔が切り替わる動作になりました。

図3

投稿2020/10/06 13:29

Bongo

総合スコア10811

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

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

vinvinvidal

2020/10/06 14:33

御回答ありがとうございます。 なるほどUVは複数持てるのですね、とても勉強になります。 私も自分なりに少し試してみました。 UV2で全頂点をx0y0やx1y1の様な極端な位置に配置してシェーダー側のifで割り振れば 同じsharedMaterialを使っているメッシュ達を全く違う処理に分岐させる事ができました。 効率が良いかは別として、全編通して一つのマテリアルで済ませる事もできる気がします。 まさに求めていたものです、本当にありがとうございます。
vinvinvidal

2020/10/07 21:00

すみません、追記です。 御教示頂いた方法を参考にシェーダーに分岐を仕込んでいたのですが、 UnityEditor上の実行ではうまく行っていた分岐がビルドすると機能しなくなってしまいました。 4番目のUVに仕込んでいたのですが、使用されていないUVがビルド時に整理されて番号が変わってしまうとかありそうな予感がしています。 ちょっと追うのが重そうなので一旦置いておこうと思います。 頂戴した御回答は本当に勉強させて頂きました、誠にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問