はじめに
通常のゲームオブジェクトと完全に同一のマテリアル、シェーダを使用しているはずなのに、ECSで描画するとオブジェクトが白っぽく、色が薄くなる場合があります。
左:通常のGameObjectによる描画
右:ECSからの描画
少し薄くなっているのがわかるでしょうか?
同一のPrefab、同一のシェーダにBaseColor、EmissionColorなど同じ色を書き込んでいるのですが、このように差が出る状態となっていました。
状況
ECS側の色の書き込み方法を記述しておきます。
シェーダ:シェーダグラフを使用したシェーダを使用(下図)
Colorの書き込み方法:MaterialProperty属性を使用した書き込み
[MaterialProperty("_BaseColor")]
public struct BaseColorProperty : IComponentData
{
public float4 Value;
}
[MaterialProperty("_EmissionMap")]
public struct EmissionMapProperty : IComponentData
{
public float4 Value;
}
[MaterialProperty("_EmissionColor")]
public struct EmissionColorProperty : IComponentData
{
public float4 Value;
}
※EmissionMapは本来のEmissionMapではなく光り具合調整用の独自のものです。
このように設定しておき、BaseColorPropertyというICompoenentを継承したComponentに値を書き込むとShaderGraphの_BaseColorというReferenceに反映されるようになっています。
で書き込んだ結果が先程お見せした若干色が薄くなり、白っぽく表示されるというものです。
対策
Unity内部の詳細は不明ですが、暫定的な対処としては書き込む色自体は完全に同じものを書き込んでいるのですが、どうも色空間の変換を何処かで行っており、ShaderGraph上で色空間をリニアに変換してやると意図した表示になるようでした。
ECSのマテリアルプロパティ経由で書き込んだときに変換されているのか、
通常のGameObjectのマテリアルに対して
mat.SetColor(“_BaseColor”, data.Color);のように書き込んだときに変換が発生しているのか不明ですが、
いずれにせよECSで使用するシェーダグラフ上で色空間をガンマからリニアに変換する処理を追加したところ表示が一致しました。
参考までに貼っておきます。
本来やりたいことはPowerブロックだけですが、それだけだと警告が出たので入力にAbsoluteブロックを追加して警告が出ないようにしています。
こちらの補正を行うことで、薄くなっていた色が意図した色に近づくことが確認できました。
※色が変わってしまう真因まで探っていないので、本当にこの変換が正しいという保証はありません。
このため、完全に一致していない可能性もあるのでその点ご注意ください。
「この変換をすると、見た目が近づく」ぐらいの受けとりにしていただけるとよいかもしれません。
また、シェーダ上ではなく書き込み時にScript上で色変換しても同じ結果が得られると思います。
さいごに
これに関してはさっぱり原因がわからなかったので、結構対応に苦労しました。
結果的に真因まではわかりませんでしたが、本記事が誰かのお役に立てば幸いです。
コメント