特定平台的渲染差异

Unity 在不同的平台上运行,而且在某些情况下存在运行差异。大部分时间里 Unity 都向您隐藏差异,但有时您仍然可以撞见它们。

渲染纹理坐标

垂直纹理坐标的惯例与 Direct3D、OpenGL 和 OpenGL ES 不同:

大多数时候这都无关紧要,除了渲染到渲染纹理时。在此情况下,Unity 渲染到 Direct3D 上的纹理时,在内部翻转渲染,以便平台之间的惯例匹配。

当使用图像效果和抗锯齿 (Anti-Aliasing) 时,不会出现这种情况。在此情况下,Unity 渲染到屏幕以获得抗锯齿选项,然后将渲染“解析”为 RenderTexture 以便用图像效果 (Image Effect) 进一步处理。产生的图像效果的源纹理在 Direct3D 上没有翻转(不同于其他所有的渲染纹理 (Render Texture))。

如果图像效果 (Image Effect) 简单(一次处理一个纹理),这无关紧要,因为 Graphics.Blit 会进行处理。

然而,如果在图像效果 (Image Effect) 中同时处理一个以上的 RenderTexture,它们很可能会在不同的垂直方向出现(仅在类似 Direct3D 的平台上,并且仅在使用抗锯齿选项时)。您需要在顶点着色器中手动“翻转”屏幕纹理,像这样:

//在 D3D 上使用 AA 时,主纹理与场景深度纹理
//将在不同垂直方向出现。
//因此在这种情况下翻转纹理采样(主纹理
//纹理元件大小将为 Y 轴负值)。
#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
        uv.y = 1-uv.y;
#endif

请在着色器替换样例工程中查看边缘检测 (Edge Detection) 场景以了解这样的示例。此处的边缘检测同时使用屏幕纹理和相机的深度 + 法线纹理

Alpha 测试 (AlphaTest) 和可编程着色器

某些平台,尤其是手机 (OpenGL ES 2.0) 和 Direct3D 11,没有固定函数 alpha 测试功能。使用可编程着色器时,建议改为使用像素着色器的 Cg/HLSL clip() 函数。

Direct3D 11 着色器编译器对语法更挑剔

Direct3D 9 和 OpenGL 使用 NVIDIA 的 Cg 来编译着色器,但 Direct3D 11(和 Xbox 360)使用 Microsoft 的 HLSL 着色器编译器。HLSL 编译器对着色器各种细微错误更挑剔。例如,它不接受没有适当初始化的函数输出值。

您会遇到此类情况的最常见位置是:

      void vert (inout appdata_full v, out Input o) 
      {
        UNITY_INITIALIZE_OUTPUT(Input,o);
        // ...
      }

DirectX 11 HLSL 语法和表面着色器 (Surface Shader)

当前表面着色器编译管线的有些部分无法理解特定于 DX11 的 HLSL 语法。如果是诸如 StructuredBuffers、RWTextures 和其他非 DX9 语法的 HLSL 功能,则您必须将其纳入只有 DX11 的预处理宏:

    #ifdef SHADER_API_D3D11
    // 特定于 DX11 的编码,如
    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 完全相同,但缺失以下内置参数:

iPad2、MSAA 和 alpha 混合几何结构

当 MSAA 已激活并且用 RGBA colorMask 绘制 alpha 混合几何结构时,Apple 驱动程序有产生假象的错误。为避免出现假象,遇到此配置时我们强制使用 RGBA colorMask,尽管它会将内置 Glow FX 渲染成无法使用(因为它需要 DST_ALPHA 获取强度值)。同时,如果您自己编写程序,请更新着色器(请参阅Pass Docs)中的“渲染设置 (Render Setup) -> ColorMask”。)

Page last updated: 2013-06-28