1)URPでのBRDF計算式の問題
2)Job Systemがメインスレッドの時間を占めるという問題
3)ProfilerでTempBufferの問題を特定する
4)Unity2019でHDRPのカメラのGL線画の問題
5)UnityWebCamTextureによって取得されたカメラ画像が回転される
Shader
Q:最近URP Shaderを見ているときに問題が見つかりました。それが間違っているかどうかわかりませんが、最初にコードを貼り付けます。
1つ目は、URPのLighting.hlslでBRDFを初期化する部分です。
inline void InitializeBRDFData(half3 albedo, half metallic, half3 specular, half smoothness, half alpha, out BRDFData outBRDFData)
{
#ifdef _SPECULAR_SETUP
half reflectivity = ReflectivitySpecular(specular);
half oneMinusReflectivity = 1.0 - reflectivity;
outBRDFData.diffuse = albedo * (half3(1.0h, 1.0h, 1.0h) - specular);
outBRDFData.specular = specular;
#else
half oneMinusReflectivity = OneMinusReflectivityMetallic(metallic);
half reflectivity = 1.0 - oneMinusReflectivity;
outBRDFData.diffuse = albedo * oneMinusReflectivity;
outBRDFData.specular = lerp(kDieletricSpec.rgb, albedo, metallic);
#endif
outBRDFData.grazingTerm = saturate(smoothness + reflectivity);
outBRDFData.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(smoothness);
outBRDFData.roughness = max(PerceptualRoughnessToRoughness(outBRDFData.perceptualRoughness), HALF_MIN);
outBRDFData.roughness2 = outBRDFData.roughness * outBRDFData.roughness;
outBRDFData.normalizationTerm = outBRDFData.roughness * 4.0h + 2.0h;
outBRDFData.roughness2MinusOne = outBRDFData.roughness2 - 1.0h;
#ifdef _ALPHAPREMULTIPLY_ON
outBRDFData.diffuse *= alpha;
alpha = alpha * oneMinusReflectivity + reflectivity;
#endif
}
私の理解では:
- outBRDFData.perceptualRoughnessは、粗さで、ラフネスと呼ばれるものです。
- outBRDFData.roughnessは、粗さの2乗です。
- outBRDFData.roughness2は、粗さの4乗です。
URPのLighting.hlslでBRDFを計算する部分を見てください。
// Based on Minimalist CookTorrance BRDF
// Implementation is slightly different from original derivation: http://www.thetenthplanet.de/archives/255
//
// * NDF [Modified] GGX
// * Modified Kelemen and Szirmay-Kalos for Visibility term
// * Fresnel approximated with 1/LdotH
half3 DirectBDRF(BRDFData brdfData, half3 normalWS, half3 lightDirectionWS, half3 viewDirectionWS)
{
#ifndef _SPECULARHIGHLIGHTS_OFF
float3 halfDir = SafeNormalize(float3(lightDirectionWS) + float3(viewDirectionWS));
float NoH = saturate(dot(normalWS, halfDir));
half LoH = saturate(dot(lightDirectionWS, halfDir));
// GGX Distribution multiplied by combined approximation of Visibility and Fresnel
// BRDFspec = (D * V * F) / 4.0
// D = roughness^2 / ( NoH^2 * (roughness^2 - 1) + 1 )^2
// V * F = 1.0 / ( LoH^2 * (roughness + 0.5) )
// See "Optimizing PBR for Mobile" from Siggraph 2015 moving mobile graphics course
// https://community.arm.com/events/1155
// Final BRDFspec = roughness^2 / ( NoH^2 * (roughness^2 - 1) + 1 )^2 * (LoH^2 * (roughness + 0.5) * 4.0)
// We further optimize a few light invariant terms
// brdfData.normalizationTerm = (roughness + 0.5) * 4.0 rewritten as roughness * 4.0 + 2.0 to a fit a MAD.
float d = NoH * NoH * brdfData.roughness2MinusOne + 1.00001f;
half LoH2 = LoH * LoH;
half specularTerm = brdfData.roughness2 / ((d * d) * max(0.1h, LoH2) * brdfData.normalizationTerm);
// On platforms where half actually means something, the denominator has a risk of overflow
// clamp below was added specifically to "fix" that, but dx compiler (we convert bytecode to metal/gles)
// sees that specularTerm have only non-negative terms, so it skips max(0,..) in clamp (leaving only min(100,...))
#if defined (SHADER_API_MOBILE) || defined (SHADER_API_SWITCH)
specularTerm = specularTerm - HALF_MIN;
specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles
#endif
half3 color = specularTerm * brdfData.specular + brdfData.diffuse;
return color;
#else
return brdfData.diffuse;
#endif
}
ここでの最終的な式は次のとおりです。
BRDFspec=roughness^2/( NoH^2*(roughness^2-1)+1)^2*(LoH^2*(roughness+0.5)*4.0)
次に、コードに記述されているアドレスであるUnityの2015年の記事を見てください。
コードにあるroughnessは、実際には画像のroughnessの2乗です。混乱を防ぐために、以下はroughness©和roughness(n)で表します。
roughness©=roughness(n)^2
これを見ながら、少し混乱になっています。
論文のroughness(n)+0.5ステップはコードに対応したら、roughness©^0.5+0.5
はずだが、URPコードでroughness©+0.5を直接使用します。これは私の理解が間違っているか、それともURPのShaderが間違っているか。
A:未熟な見方ですが、私の結論は次のとおりです。
2乗roughness(n)^2プラス5は妥当です
1乗と2乗のどちらを使用してもほとんど違いはありません
SIGGRAPHレポートの元のVF関数は次のとおりです。
使用される実際のVF関数は、上記の関数の近似値であり、画像に近い関数を使用して最適化します。
次のように作者は1乗と2乗をとる関数を画像化します。
2つの画像はそれほど違いがなく、傾向から見れば、2乗を取るのは元のVFに近いように見えます(Modified KSK and Schlick Fresnel depend on LH)。
作者は、Lighting.hlslのコードを変更して、最初の1乗を使用します。
outBRDFData.normalizationTerm=outBRDFData.perceptualRoughness*4
同じ画面でroughness(n)+0.5とroughness(n)^2+0.5
を使用してマテリアルを描画すると、ほとんど違いはありません。
グラフィックスの最初の法則によると、見た目が正しければ正しいので、両方が正しいことを理解するのは問題ありません。そうすれば、差が大きくなければ、掘り下げる必要がないということでしょうか。
Script
Q:下図に示すように、Job Systemで実行したのにメインスレッドの時間を占めるのはなぜですか?
A:子スレッドの実行が終了するのを待ちます。
Rendering
Q:写真に示されているように、シーンにある2つのTempBufferはC#スクリプトから作成したわけではありません。シーンはAfterEffectsを使用せず、Grab PassのShaderも使用せずに、シーンカメラはMSAAとHDRをオフにしており、これら2つのTempBufferがまだあります。それを完全に取り除く方法は?
これは、次の2つのことと関わりそうです。
A1:次のように設定してみてください:Camera.forceIntoRenderTexture = false;
このオプションは、カメラを強制的にTempBufferにレンダリングします。
AfterEffectsを使用しない場合は手動でfalseに設定し、AfterEffectsを有効にすると自動的にtrueに設定します。したがって、After Effectsを使用する場合、TempBufferは避けられません。
A2:すべてのMonoBehaviorのOnRenderImage(RenderTexture source、RenderTexture destination)関数をブロックします。一般的に、各OnRenderImage(RenderTexture source, RenderTexture destination)
関数は一つのTempBufferを生成します。
A3:Grab RenderTextureは通常、Depthが最小のカメラのClear FlagsがDepth Onlyに設定されている場合に表示されます。
Rendering
Q:Unity 2019.3.0f6で、GL線画を使うと、Gameビューにカメラが見つかりません。プロジェクトはHDRPプロジェクトに属しています。
A1:GL描画をGLDraws()に配置してください。Unity2020.2.2f1c1で、HDRP10.2.2環境で効果を正常に描画しました。
protected void OnEnable()
{
if (GraphicsSettings.renderPipelineAsset != null)
RenderPipelineManager.endFrameRendering += OnCameraRender;
}
protected void OnDisable()
{
if (GraphicsSettings.renderPipelineAsset != null)
RenderPipelineManager.endFrameRendering -= OnCameraRender;
}
protected void OnCameraRender(ScriptableRenderContext context, Camera[] cameraList)
{
foreach(var camera in cameraList)
{
if (CheckFilter(camera))
GLDraws();
}
}
Script
Q:Unity WebCamTextureから取得したカメラ画像が回転されました。WeChatをスワイプしたところ、画像は正しいです。スマホを回転させると、画像は常に正しくて、回転の痕跡はありません。スマホが縦向きの場合は正常ですが、横向きに回転させると画像が正しくなくなります。
UWA Technologyは、モバイル/VRなど様々なゲーム開発者向け、パフォーマンス分析と最適化ソリューション及びコンサルティングサービスを提供している会社でございます。
今なら、UWA GOTローカルツールが15日間に無償試用できます!!
よければ、ぜひ!
UWA公式サイト:https://jp.uwa4d.com
UWA GOT OnlineレポートDemo:https://jp.uwa4d.com/u/got/demo.html
UWA公式ブログ:https://blog.jp.uwa4d.com