【UnityShader】ShaderLabのプロパティ属性 【1】#77
前回の成果
ポリゴン分解シェーダーを制作した。
今回やること
ShaderLabのプロパティの属性について解説します。
プロパティの属性とは
パラメーターに対して、inspector上から値を設定することが出来るものになります。

HideInInspector
inspector上から値を非表示にすることができます。
_HideValueが非表示になっていることがわかると思います。
Properties {
_MainTex ("Texture", 2D) = "white" {}
[HideInInspector] _HideValue ("HideValue", int) = 0
_ShowValue ("ShowValue", int) = 0
}

NoScaleOffset
テクスチャデータのTilingとOffsetを非表示にすることができます。
Properties {
[NoScaleOffset]_MainTex ("Texture", 2D) = "white" {}
}

Normal
アタッチされているテクスチャが法線マップであることを示しています。
Properties {
[Normal]_MainTex ("Texture", 2D) = "white" {}
}

なお、法線マップかはテクスチャのinspectorのTexture Typeで判断しています。

また、法線マップでは無いものをアタッチした際には警告が出ます。
試しに、Sprite(2D and UI)の元をアタッチしてみます。

すると、このテクスチャは法線マップではありませんといった旨のメッセージと、Fix Nowのボタンが出てきます。

Fix Nowを押下すると、アタッチされているテクスチャが自動で法線マップへと置き換わります。


HDR
アタッチされているテクスチャがHDRテクスチャであることを示しています。
Properties {
[HDR]_MainTex ("Texture", 2D) = "white" {}
}

HDRとは
HDRとは、普通のテクスチャ(SDRテクスチャ)よりも明るさの表現の範囲を広げたテクスチャになります。
SDRは各色を0.0~1.0で保持しているのに対し、HDRは~65504まで保持できます。
HDRを使用することにより、白飛びや黒つぶれを防ぐことが出来ます。
白飛びしているもの
【Unity】HDRってなんやねーん!という人のための解説 │ エクスプラボ:より引用
白飛びを防いだもの
HDRに関しては以下サイト様が分かりやすかったです。
なお、通常のテクスチャをアタッチしてもNormalとは違い警告はでません。

Gamma
FloatかVectorプロパティがsRGB値で指定されていて、使用するカラースペースに応じて変換が必要なことを示しています。
Properties {
_MainTex ("Texture", 2D) = "white" {}
[Gamma] _GammaFloat ("Gamma Float", float) = 0
[Gamma] _GammaVector ("Gamma Vector", Vector) = (0, 0, 0, 0)
}

カラースペースとは
立方的に記述される色の空間である。
カラースペースともいう。
色を秩序立てて配列する形式であり、色を座標で指示できる。色空間 - Wikipedia:より引用
Unityでは、リニア色空間とガンマ色空間の2つがあります。
2つの空間では、色の見え方が異なっています。
左がリニア色空間で、右がガンマ色空間の見え方となります。
リニア色空間は、数字上正しくあるためにライティングの計算などで使用されます。
ガンマ色空間は、人間の目に正しく見えるために使用されます。
リニア色空間を使用する際に、ColorプロパティはsRBGカラーで提供され、シェーダーに渡される時にリニア色空間の値へと変換されます。
しかし、FloatとVectorプロパティの場合は色空間の変換を自動で行ってくれません。
理由は、Unityから見た時にFloatとVectorプロパティはColorで使用しているのかがわからないからです。
そこで、明示的にGamma属性をつけてあげることにより、色空間の変換を行ってくれるようになります。
リニア色空間、ガンマ色空間に関しては以下サイト様が分かりやすかったです。
PerRendererData
テクスチャデータをMaterialPropertyBlockクラスのインスタンス時の値で初期化します。
inspector上では、非表示となります。
Properties {
[PerRendererData]_MainTex ("Texture", 2D) = "white" {}
}

MaterialPropertyBlockクラス
このクラスは同一マテリアルのプロパティをインスタンスせずに変えることができるクラスとなっています。
実際に実装してみます。
まず、簡単に色を変えるシェーダーを制作します。
Shader "Unlit/materialPropertyBlock" { Properties { _Color ("Color", Color) = (1, 1, 1, 1) } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; }; fixed4 _Color; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); return o; } fixed4 frag (v2f i) : SV_Target { return _Color; } ENDCG } } }
そして、このシェーダーを適当な2つのオブジェクトへとアタッチします。
オブジェクトAのinspector

オブジェクトBのinspector

同じマテリアルなので、見た目も同じとなります。
Scene上

オブジェクトAのみ赤色に変更しようとします。
オブジェクトAのマテリアルのColorプロパティを変更してみます。
オブジェクトAのinspector

しかし先程も説明した通り、同じマテリアルを使用しているためBも赤色となってしまいます。
Scene上

今回は色を変えたいだけなのに、わざわざマテリアルを複製するのも手間です。
2つ程度なら良いですが、100個、10000個となってくると話が変わってきます。
そこで、MaterialPropertyBlockの出番となります。
まずは以下のScriptを各オブジェクトにアタッチします。
using UnityEngine; public class MaterialPropertyBlockTest : MonoBehaviour { [SerializeField] private Color _color; void Start() { MeshRenderer renderer = GetComponent<MeshRenderer>(); MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock(); materialPropertyBlock.SetColor("_Color", _color); renderer.SetPropertyBlock(materialPropertyBlock); } }
そしてColorも各オブジェクトで変更してみます。
オブジェクトAのinspector

オブジェクトBのinspector

実行すると同一マテリアルなのに、各オブジェクトで色が異なっていることを確認できます。
Scene上

オブジェクトAのinspector

オブジェクトBのinspector

MainTexture
対象のプロパティが、マテリアルのメインテクスチャであることを示します。
デフォルトでは、プロパティ名が_MainTexのものをメインテクスチャとしています。
なお、複数回この属性が呼ばれた場合には一番最初のプロパティをメインテクスチャにし、後のプロパティは無視されます。
Properties {
_MainTex ("Texture", 2D) = "white" {}
[MainTexture]_SubTex1 ("Sub Texture1", 2D) = "white" {}
// MainTextureと見なされない
[MainTexture]_SubTex2 ("Sub Texture2", 2D) = "white" {}
}

MainColor
対象のプロパティが、マテリアルのメインカラーであることを示します。
デフォルトでは、プロパティ名が_Colorのものをメインカラーとしています。
なお、複数回この属性が呼ばれた場合には一番最初のプロパティをメインカラーにし、後のプロパティは無視されます。
Properties {
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1, 1, 1, 1)
[MainColor]_SubColor1 ("Sub Color1", Color) = (1, 1, 1, 1)
// MainColorと見なされない
[MainColor]_SubColor2 ("Sub Color2", Color) = (1, 1, 1, 1)
}

Space
対象のプロパティの上部にスペースを入れます。
また、値を入れることでスペースの幅を調整することができます。
Properties {
_MainTex ("Texture", 2D) = "white" {}
_NotSpace ("Not Space", int) = 0
[Space] _SpaceA ("Space A", int) = 0
[Space(50)] _SpaceB ("Space B", int) = 0
[Space(100)] _SpaceC ("Space C", int) = 0
}

今回は以上となります。
ここまでご視聴ありがとうございました。


