顶点着色器或 CPU 内部的 DirectX 11 矩阵转换

DirectX 11 Matrix Translation Inside Vertex Shader Or CPU

菲律宾共产党: https://github.com/walbourn/directx-sdk-samples/blob/master/Direct3D11TutorialsDXUT/Tutorial08/Tutorial08.cpp

HLSL: https://github.com/walbourn/directx-sdk-samples/blob/master/Direct3D11TutorialsDXUT/Tutorial08/Tutorial08.fx

在 DirectX 示例(教程 8)中,它们正在使用局部坐标初始化顶点(我想,不确定正确的术语)

// Create vertex buffer
    SimpleVertex vertices[] =
    {
        { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
        { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) },
        { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) },
        { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) },

        { XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) },
        { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
        { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) },
        { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) },

        { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) },
        { XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 1.0f ) },
        { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
        { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 0.0f ) },

        { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) },
        { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT2( 0.0f, 1.0f ) },
        { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) },
        { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 0.0f ) },

        { XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT2( 0.0f, 1.0f ) },
        { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 1.0f ) },
        { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
        { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) },

        { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) },
        { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) },
        { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 0.0f ) },
        { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
    };

但随后他们通过顶点着色器转换位置:

XMMATRIX mWorldViewProjection = g_World * g_View * g_Projection;

我的问题是:

1:如果这是一个静态对象(不是 moving/animating),您是否仍要平移世界位置(不确定正确的术语)还是要将对象放置在正确的 3D 中space/Scene 初始化顶点时,示例:

{ XMFLOAT3( CorrectWorldX, CorrectWorldY, CorrectWorldZ ), XMFLOAT2( 1.0f, 0.0f ) },

一个完美的例子就是随机生成的 level/terrain。

2:如果您使用着色器将位置定位在正确的 3d 世界中 space 而不是仅在初始化顶点时这样做,对性能有何影响?

3:对于Animation,这是角色动画骨骼转换的首选方法?

4: 构建关卡(放置物体)时,我想你别无选择,只能通过着色器平移,但你也可以保存最终位置。

希望这是清楚的,因为我正在学习 DirectX 11 和正确的做法!

  1. 静态对象只有在不可重用的情况下才应真正放置在现实世界的坐标中。然后它只是几何体,但最佳做法是将转换矩阵传递到 position/orientate 对象,从本地 space 到世界 space。例如,您会多次使用的树都会有一个指定的旋转、缩放和平移矩阵。您不仅会使用这种技术,而且会使用 "instance" 缓冲区将矩阵快速馈送到 GPU,并确保每次放置模型时 GPU 都不会停顿(使用常量缓冲区会引入轻微的停顿,因此将它们用于许多模型确实很受欢迎)。

  2. GPU 中的性能影响远低于 CPU。更不用说,GPU 中的矩阵数学就是它的面包和黄油。显然,scale/rotate/translate 矩阵需要在加载到 GPU 之前通过您的代码进行准备。 GPU 将快速将您的顶点从本地乘以到世界 space(如果您正在细分,则在顶点着色器或域着色器中)。

  3. 动画涉及到一些事情,例如每个顶点对骨骼的权重和影响。如果一个顶点受到多个骨骼点的影响,则需要在这两个骨骼点之间进行 lerping。但是,是的,GPU 最适合执行此操作。计算着色器流到顶点着色器使用的实例缓冲区是更完整和最快的计算方法。

  4. 如果你想计算一次,那么 CPU 很好,但最好只保留每个模型的矩阵实例,让 GPU 围绕顶点计算进行工作.我不会费心尝试保存这些数据,因为内存使用量会快速增长,而且您不会在性能上节省太多。事实上,情况可能更糟,因为您每次都必须将此数据加载到 GPU 中,并且您也无法获得缓存的好处。

祝你好运