【问题标题】:DirectX 11 Matrix Translation Inside Vertex Shader Or CPU顶点着色器或 CPU 中的 DirectX 11 矩阵转换
【发布时间】:2017-09-30 13:36:38
【问题描述】:

CPP: 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:如果这是一个静态对象(不移动/动画),您是否仍要转换世界位置(不确定正确的术语)还是要将对象放置在正确的 3D 空间/场景中初始化顶点,例如:

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

一个完美的例子就是随机生成的关卡/地形。

2:如果您要使用着色器将位置定位在正确的 3D 世界空间中,而不是仅在初始化顶点时这样做,性能会受到什么影响?

3:对于动画来说,这是角色动画骨骼变换的首选方法吗?

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

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

【问题讨论】:

    标签: directx-11 vertex-shader vertex


    【解决方案1】:
    1. 静态对象只有在不能重复使用的情况下才能真正放置在现实世界的坐标中。然后它只是几何,但最佳实践是传递一个平移矩阵以将对象从局部空间定位/定向到世界空间。例如,您将多次使用的树都会有一个分配的矩阵用于旋转、缩放和平移。您不仅会使用这种技术,而且会使用“实例”缓冲区将矩阵快速提供给 GPU,并确保每次放置模型时 GPU 中都不会出现停顿(使用常量缓冲区会引入轻微的停顿,因此使用它们对于许多模型确实很受欢迎)。

    2. GPU 中的性能影响远低于 CPU 中的性能。更不用说,GPU 中的矩阵数学是它的生计。显然,缩放/旋转/平移矩阵需要在加载到 GPU 之前通过您的代码进行准备。 GPU 将快速将您的顶点从本地空间乘以世界空间(如果您正在细分,则在顶点着色器或域着色器中)。

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

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

    祝你好运

    【讨论】:

    • 谢谢!正是我想要的!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-31
    • 2021-12-27
    • 1970-01-01
    相关资源
    最近更新 更多