はじめに
Unity C# で作成したメッシュをParticleSystemで使用したとき、頂点カラーの表示が壊れました。
この現象の原因の考察・および回避方法をまとめようと思います。
以下のような頂点カラーを設定すると、ParticleSystemで表示したときに頂点カラーが壊れます。
mesh.colors = colors; // Color[]
環境
Unity 2020.2.0f1
Universal RP 10.2.2
mesh.colorに頂点カラーを設定
mesh.colorsに頂点カラーを設定してメッシュを作成したとします。
mesh.colors = colors; // Color[]
頂点カラー情報は メッシュに16byte カラーとして保存されます。
MeshRenderer で表示した場合
このメッシュをMeshRendererで描画した際は、色が正常に表示されます。
メッシュのマテリアルにはシェーダーグラフを使用しており、頂点カラーをMasterノードとして出力しています。
ParticleSystem で表示した場合
このメッシュをParticleSystemで表示すると色が壊れます。
mesh.colors は Color であるのに対して、Particle Systemでは頂点カラーは Color32 として扱われていることが理由だと考えられます。
以下のように32bitカラーを設定すれば、色が壊れる現象は回避できます。
mesh.colors32 = colors32; // Color32[]
Colors32 は 4byteカラー(32bitカラー)としてメッシュに保存されます。
色が壊れる理由について
ParticleSystemのカラーはColors32
Unityの ParticleSystemは頂点カラーをColor32として持っているようです。
たとえばParticleSystem.csの中を見ると、ParticleSystem.startColorはColor32型で定義されています。
/// <summary> /// <para>The initial color of the particle. The current color of the particle is calculated procedurally based on this value and the active color modules.</para> /// </summary> public Color32 startColor
ドキュメントが見つからなかったので断言はできませんが、ParticleSystemはメモリ領域からColor32[ ]を読んでいると考えられます。
そして、メッシュの頂点カラー領域にColor[ ] が設定されていた場合、色が壊れます。
16byte カラーを設定したときのメモリ領域
RGBA = (0.5, 0.5, 0.5 ,1.0) という灰色を メッシュのColorに設定したとします。
メモリ上では、以下のような32bit Float値が4つ並びます。
ParticleSystemは32bitカラーとして解釈
ParticleSystemは頂点カラーのことを Color32 だと思っているので、カラー情報を以下のように読み取ります。
1つの16byte カラーは 4つの32bit カラーとして解釈されます。
0.5を 32bit カラーとして解釈された場合
0.5という32bit float のビット列は、以下のような32ケタの2進数になります。
ParticleSystemはこれをbyte が4つ並んだRGBAカラーとして解釈し、RGBA = (63, 0, 0, 0) になります。
RGBA = (63, 0, 0, 0) は画面上では以下のような色として表示されます。
0.6 を32bitカラーとして認識した場合
Rチャンネルが0.6だった場合も考えてみます。
0.6という32bit floatのビット列は以下のようになります。
このビット列を32bit RGBAカラーとして解釈すると、RGBA = (63, 25, 153, 154) になります。
RGBA = (63, 25, 153, 154)は画面上では以下のような色として表示されます。
まとめ
Color[] を 頂点カラーに設定すると、想定とは異なる色が表示されてしまうことがわかりました。
メッシュを作成するときは以下のように32bitカラーを設定すれば、色が壊れる現象を回避できます。
mesh.colors32 = colors32; // Color32[]
関連
単精度浮動小数点数
https://www.wikiwand.com/ja/%E5%8D%98%E7%B2%BE%E5%BA%A6%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E7%82%B9%E6%95%B0#
【Unity】【シェーダ】小数点の精度と型の使い分けについて(float / half / fixedの話)
https://light11.hatenadiary.com/entry/2018/06/01/001008
Color と Color32 の違い
http://nakamura001.hatenablog.com/entry/20120822/1345658342