カメラのDepth Texture
シェーダ LOD

プラットフォーム別のレンダリングの違い

Unityは様々なプラットフォームで動作し,いくつかのケースでは動作に違いが出ます。ほとんどの場合,Unityは違いを隠してくれますが,それでも表面化する場合があります。

Render Textureの座標

垂直方向のテクスチャ座標の表現方法ははDirect3DとOpenGL・OpenGL ESで異なります。

  • Direct3Dでは最上部がゼロの座標位置となり,下方向に行くにしたがって増加します。
  • OpenGLとOpenGL ESでは,最下部がゼロの座標位置となり,上方向に行くにしたがって増加します。

ほとんどの場合に影響はありませんが,Render Texture に対してレンダリングする場合は影響があります。この場合,UnityはDirect3Dでレンダリングするときに意図的にレンダリングを上下逆に反転するので,プラットフォーム間のルールは同じままです。

この反転が行われないケースは,Image Effects およびアンチエイリアスが使用される場合です。この場合,Untyはアンチエイリアスして,後続のイメージエフェクトの処理のためにRender Textureに対してレンダリングを“溶かし込みます”。結果となるイメージエフェクトのソーステクスチャはDirect3Dで_上下逆ではありません_ (他のRender Textureと違って)。

もしイメージエフェクトがシンプルである(1回にテクスチャを1つのみ処理する)場合,Graphics.Blit が処理してくれるため,このことを気にする必要はありません。

しかし, イメージエフェクトで1回にRender Textureを複数まとめる場合 ,多くのケースでそれぞれが異なる垂直方向に出力されます(ただしDirect3Dのようなプラットフォームであり,かつアンチエイリアスが使用されている場合のみ)。頂点シェーダで手動で画面テクスチャを上下逆に“反転” する必要があります。

// On D3D when AA is used, the main texture and scene depth texture
// will come out in different vertical orientations.
// So flip sampling of the texture when that is the case (main texture
// texel size will have negative Y).

#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
        uv.y = 1-uv.y;

#endif

Shader Replacement サンプルプロジェクト でエッジ検出を行っているシーンを確認下さい。ここでエッジ検出はシーンのテクスチャとカメラデプスおよび法線テクスチャ の両方で使用されています。

アルファテストおよびプログラマブル シェーダ

いくつかのプラットフォーム,殊更にモバイル(OpenGL ES 2.0)およびDirect3D 11では,Fixed Function(固定関数)alpha testing (アルファテスト)機能がありません。プログラマブル シェーダを使用する場合,Cg/HLSL clip() 関数を代わりに使用することを推奨します。

Direct3D 11シェーダコンパイラは文法に厳格

Direct3D 9やOpenGLはNVIDIAのCgを使用してシェーダをコンパイルしますが, Direct3D 11 (およびXbox 360)はMicrosoftのHLSLシェーダコンパイラを使用します。HLSLコンパイラは様々なところでシェーダの僅かなエラーに対して厳格です。例をあげると,正しく初期化されていない関数の出力値があると受付をしてくれません。

この現象に最も頻繁に遭遇する場面は:

  • Surface shader 頂点モディファイアの場合。次のように必ず出力を初期化するようにして下さい: void vert (inout appdata_full v, out Input o) { UNITY_INITIALIZE_OUTPUT(Input,o); // … }

  • 部分的に初期化された値,例えばfloat4を戻す関数があるけれど,コードが.xyzしか戻さない場合。全ての値を戻すか,float3で良いのならばそのように変更します。

  • tex2D を頂点シェーダで使用する時。頂点シェーダでは UV デリバティブが存在しないため無効です。その代わりに明示的に ミップ レベルのサンプリングを追加する必要があり,例えば tex2Dlod (tex, float4(uv,0,0)) を使用します。OpenGL で正しく動作させるためには #pragma glsl を追加する必要があります。

DirectX 11 HLSL 文法および サーフェイス シェーダ

現在 サーフェイス シェーダ の一部のコンパイル パイプラインでは DirectX 11 特有の HLSL 文法が解釈されません。もし StructuredBuffers, RWTextures およびその他の 非 DirectX 9 文法の HLSL 機能を使用する場合,DirectX 11 専用のプリプロセッサ マクロにラッピングする必要があります:

    #ifdef SHADER_API_D3D11
    // DX11-specific code, e.g.
    StructuredBuffer<float4> myColors;
    RWTexture2D<float4> myRandomWriteTexture;
    #endif

OpenGL ES 2.0でOpenGLシェーダ言語(GLSL)のシェーダを使用する

OpenGL ES 2.0は,OpenGLシェーダ言語(GLSL)についてネイティブサポートが限定されていて,例えばOpenGL ES 2.0のレイヤーはシェーダに対して,内蔵パラメータを提供していません。

Unityは内蔵パラメータをOpenGLと全く同じように実装していますが,次のパラメータが欠落しています:

  • gl_ClipVertex
  • gl_SecondaryColor
  • gl_DepthRange
  • gl_LightSourceParameters構造体のhalfVectorプロパティ
  • gl_FrontFacing
  • gl_FrontLightModelProduct
  • gl_BackLightModelProduct
  • gl_BackMaterial
  • gl_Point
  • gl_PointSize
  • gl_ClipPlane
  • gl_EyePlaneR, gl_EyePlaneS, gl_EyePlaneT, gl_EyePlaneQ
  • gl_ObjectPlaneR, gl_ObjectPlaneS, gl_ObjectPlaneT, gl_ObjectPlaneQ
  • gl_Fog

iPad2とMSAAとアルファブレンディングされた形状

Appleのドライバーにはバグがあり,MSAAを有効化した場合かつRGBA colorMaskでない形でアルファブレンディングされた形状が描画された場合,画像の乱れが生じます。画像の乱れを防止するために,内蔵Glow FXを無効にしてしまう(DST_ALPHAをintensityの値として必要であるため)にも関わらずRGBA colorMaskを強制的に有効にします。

カメラのDepth Texture
シェーダ LOD