概要
こちらの記事では、現在clusterにて特定のワールドやアクセサリー、アバターを使用することで発生する、以下の画像のように黒点付きで白飛びする現象の原因とその対策方法についてご説明いたします。

原因について
オブジェクトを描画するシェーダーにおいて計算過程で不正な値(いわゆるNaN)のピクセルが発生し、その不正な値を基に PostProcessing にてブラー処理(ブルーム、被写界深度など)がされることで「NaNの伝播(Propagating NaNs)」という現象が起きてしまい、その結果として本現象が発生いたします。
特に、iOS 17以降のグラフィック環境ではNaNの伝搬が発生すると強い白飛びが一緒に発生し、以下のような描画結果となります。

不正な値となったピクセルは動作環境によって黒点もしくは白点となることを確認しています。黒点なしで過剰な白飛びが発生している場合も、その中心点のピクセルが不正な値となっている可能性があります。
グラフィックエンジニアリングに精通している方向けの資料となりますが、本現象と同様の現象はUnity公式からも紹介がされておりますのであわせてご確認ください。
Understand Not a Number (NAN) and Infinite (Inf) values
本現象の解消には、原因となるオブジェクトの描画まわりの修正が必要となります。
原因となるオブジェクトの見つけ方
まずは本現象を引き起こしているオブジェクトを見つける必要があります。 iOSなどの一部環境に限定して調査する場合は テスト用スペース の機能もご活用ください。
特定のオブジェクトが原因の場合
ブルームや被写界深度(DepthOfField)といったブラー処理を持つ PostProcessing を有効にしたワールドで黒点や白飛びが発生した場合、その中心部分にあるオブジェクトの描画が原因と考えられます。
そのため、例えばブルームを有効にしたワールドで以下のような描画結果が確認された場合は、黒点部分の「球体オブジェクト」が原因であると推測できます。


原因と思われるオブジェクトが見つかった場合、まずはそのオブジェクトだけを非表示にしたワールドをアップロードしてご確認ください。ここで本現象が解消された場合は、非表示にしたオブジェクトが原因と特定できます。

また、白飛びが強すぎてオブジェクトが確認しづらい場合は、まずブルームを無効にし、代わりに被写界深度である DepthOfField を設定するパターンをお試しください。ブルームの場合と異なり黒点のみとなるため、原因オブジェクトも見つけやすくなる可能性があります。


ワールドにあるオブジェクトだけでなく本現象が発生するアクセサリーやアバターも同様に、ブラー処理を持つPostProcessingが有効なワールドで確認できます。
ワールド全体で本現象が発生する場合
特定のオブジェクトにかかわらずワールド全体で過剰な白飛びが発生する場合は、シーンのライティング情報が不正な値を持っている可能性があります。詳しくは 特定のワールドでアバターやオブジェクトが真っ黒になる現象、及びiOS 17で白く光る現象について をご参照ください。

次項からは、現象が確認されたオブジェクトの改修方法について紹介します。
CCKワールド向けの解決アプローチ
CCK製ワールドで本現象が発生する場合は、以下のようなアプローチをお試しください。
原因オブジェクトのシェーダーを変更する
本現象が発生しているオブジェクトのマテリアルに指定されたシェーダーを変更します。環境によって不正な結果が出力されやすいシェーダーもあるため、再度発生するようであればさらに別のシェーダーをお試しください。
原因オブジェクトのモデルを改修する
特に以下のデータが起因となっているパターンが確認されております。
- メッシュの頂点法線
- マテリアルに指定するノーマルマップテクスチャ
特に法線まわりは正しく正規化(Normalize)されていること、ゼロベクトルではないことをご確認ください。
ライティングデータを修正する
一部のワールドではStandardシェーダーを使っているオブジェクトにおいても、ライティングデータを組み合わせることで本現象もしくは過剰に白飛びする現象を確認しております。
シーンからライティングデータを消すことで本現象が解消される場合は、ベイクされたライティングデータが原因となっている可能性があります。その場合は、シーンの光源設定を見直した上で再度ベイクを行ってください。

また、輝度の差が大きいHDRテクスチャのSkyboxを使用してベイクしている場合は、Skyboxが原因となっている可能性があります。詳しくは 特定のワールドでアバターやオブジェクトが真っ黒になる現象、及びiOS 17で白く光る現象について をご参照ください。
シェーダーに回避策を入れる
こちらの対策はシェーダーを書ける方向けの紹介となりますが、シェーダーでNaNを回避するコードをいれることで本現象を回避できる可能性があります。
参考として、clamp関数を使用して回避する方法を紹介します。以下の様に clamp関数 を通すことで、それ以前でNaNであった数値が範囲内の数値に変更され、結果的に不正な値のピクセルが出力されることを回避できます。
float3 normalWS = GetWorldSpaceNormalDir(i);
#if SHADER_API_METAL && SHADER_API_MOBILE
normalWS = clamp(normalWS, -1.0, 1.0);
#endifclusterで使用しているシェーダーの一部でも同様の対応により本現象の発生を抑制しております。
アクセサリー・アバター向けの解決アプローチ
アクセサリーとアバターに関しては、今後cluster側で本現象を一部回避する対応をシェーダーに入れる予定ではありますが、モデルデータによってはその後も問題が回避できない可能性があります。
そのため、現象を確認したアクセサリーやアバターについては、モデルデータの改修と再アップロードが必要です。
モデルを改修する
特に以下のデータが起因となっているパターンが確認されております。
- メッシュの頂点法線
- マテリアルに指定するノーマルマップテクスチャ
特に法線まわりは正しく正規化(Normalize)されていること、及びゼロベクトルになっていないことをご確認ください。
















