Direct3D编译器语法Direct3D平台使用MicrosoftHLSL语义着色器值

Direct3D编译器语法Direct3D平台使用MicrosoftHLSL语义着色器值

const的使用在 Microsoft HSL(请参阅)和 OpenGL 的 GLSL(请参阅Wikipedia)着色器语言之间有所不同。

最好是遵循 OpenGL 的 GLSL 语义,并且只有当变量真正不变时才将变量声明为const。避免使用其他一些可变值初始化const变量(例如,作为函数中的局部变量)。这一原则也适用于 Microsoft 的 HLSL,因此以这种方式使用const可以避免在某些平台上混淆错误。

着色器使用的语义

要让着色器在所有平台上运行,一些着色器值应该使用以下语义:

将网格渲染为点时,从顶点着色器输出PSIZE语义(例如,将其设置为 1)。某些平台(如 OpenGL ES 或 Metal)在未从着色器写入点大小时会将点大小视为“未定义”。

有关更多详细信息,请参阅有关着色器语义的文档。

Direct3D 着色器编译器语法

Direct3D 平台使用 Microsoft 的HLSL 着色器编译器。对于各种细微的着色器错误,HLSL 编译器比其他编译器更严格。例如,它不接受未正确初始化的函数输出值。

使用此编译器时,您可能遇到的最常见情况是:

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

着色器中的 DirectX 11 (DX11) HLSL 语法

表面着色器编译管线的某些部分不能理解特定于 DirectX 11 的 HLSL(Microsoft 的着色器语言)语法。

如果您正在使用 HLSL 功能(比如StructuredBuffers、RWTextures和其他非 DirectX 9 语法)创作人,请将它们包裹在 DirectX X11 专用的预处理器宏中,如下例所示。

# ifdef SHADER_API_D3D11 
// DirectX11 专用代码,例如 
StructuredBuffer

使用着色器帧缓冲提取

一些 GPU(最明显的是 iOS 上基于 PowerVR 的 GPU)允许您通过提供当前片元颜色作为片元着色器的输入来进行某种可编程混合(请参阅上的EXT_shader_framebuffer_fetch)。

可在 Unity 中编写使用帧缓冲提取功能的着色器。要执行此操作,请在使用 HLSL(Microsoft 的着色语言,请参阅)或 Cg(Nvidia 的着色语言,请参阅nvidia.co.uk)编写片元着色器时使用inout颜色参数。

以下示例采用的是 Cg 语言。

CGPROGRAM 
// 只为可能支持该功能的平台(目前是 gles、gles3 和 metal) 
// 编译着色器 
# pragma only_renderers framebufferfetch 
void frag (v2f i, inout half4 ocol : SV_Target) {   
  // ocol 可以被读取(当前帧缓冲区颜色)  
  // 并且可以被写入(将颜色更改为该颜色)  
  // ... 
}   
ENDCG

着色器中的深度 (Z) 方向

深度 (Z) 方向在不同的着色器平台上不同。

DirectX 11、DirectX 12、PS4、Xbox One、Metal:反转方向

其他平台:传统方向

请注意,使反转方向深度 (Z) 与浮点深度缓冲区相结合,可显著提高相对于传统方向的深度缓冲区精度。这样做的优点是降低 Z 坐标的冲突并改善阴影,特别是在使用小的近平面和大的远平面时。

因此,在使用深度 (Z) 发生反转的平台上的着色器时:

但是,以下宏和函数会自动计算出深度 (Z) 方向的任何差异:

提取深度缓冲区

如果要手动提取深度 (Z) 缓冲区值,则可能需要检查缓冲区方向。以下是执行此操作的示例:

float z = tex2D(_CameraDepthTexture, uv); 
# if defined(UNITY_REVERSED_Z)   
z = 1.0f - z; 
# endif

使用裁剪空间

如果要手动使用裁剪空间 (Z) 深度,则可能还需要使用以下宏来抽象化平台差异:

float clipSpaceRange01 = UNITY_Z_0_FAR_FROM_CLIPSPACE(rawClipSpace);

注意:此宏不会改变 OpenGL 或 OpenGL ES 平台上的裁剪空间unity渲染器,因此在这些平台上,此宏返回“-near”1(近平面)到 far(远平面)之间的值。

投影矩阵

如果处于深度 (Z) 发生反转的平台上,则GL.GetGPUProjectionMatrix()返回一个还原了 z 的矩阵。 但是,如果要手动从投影矩阵中进行合成(例如,对于自定义阴影或深度渲染)unity渲染器,您需要通过脚本按需自行还原深度 (Z) 方向。

以下是执行此操作的示例:

var shadowProjection = Matrix4x4.Ortho(...);
//阴影摄像机投影矩阵 
var shadowViewMat = ...     
//阴影摄像机视图矩阵 
var shadowSpaceMatrix = ... 
//从裁剪空间到阴影贴图纹理空间     
//当引擎通过摄像机投影计算设备投影矩阵时, 
//"m_shadowCamera.projectionMatrix"被隐式反转 
m_shadowCamera.projectionMatrix = shadowProjection; 
//"shadowProjection"在连接到"m_shadowMatrix"之前被手动翻转, 
//因为它被视为着色器的其他矩阵。 
 if(SystemInfo.usesReversedZBuffer) {    
  shadowProjection[2, 0] = -shadowProjection[2, 0];    
  shadowProjection[2, 1] = -shadowProjection[2, 1];   
  shadowProjection[2, 2] = -shadowProjection[2, 2];  
  shadowProjection[2, 3] = -shadowProjection[2, 3]; 
}    
m_shadowMatrix = shadowSpaceMatrix * shadowProjection * shadowViewMat;

深度 (Z) 偏差

Unity 自动处理深度 (Z) 偏差音效,以确保其与 Unity 的深度 (Z) 方向匹配。但是,如果要使用本机代码渲染插件,则需要在 C 或 C++ 代码中消除(反转)深度 (Z) 偏差。

深度 (Z) 方向检查工具

文章来源:https://www.bilibili.com/read/cv10907247/