c++ - 在 hlsl 着色器中设置全局参数的正确方法是什么?

标签 c++ 3d hlsl direct3d11

在 hlsl 着色器中设置全局参数的正确方法是什么?如果我有以下全局参数:

float4x4 World;
float4x4 View;
float4x4 Projection;

我在顶点着色器中使用它们:

void VertexShaderFunction( in float4 inputPosition : POSITION, in float4 colorIn : COLOR, out float4 posOut : SV_POSITION, out float4 colorOut : COLOUR)
{   
    //Set values for output
    float4 worldPosition = mul(inputPosition, World);
    float4 viewPosition = mul(worldPosition, View);
    float4 position = mul(viewPosition, Projection);


    posOut = position;
    colorOut = colorIn;
}

然后如何从 C++ 代码 f.e. 设置这些全局值?什么时候移动相机?我是否应该创建另一个着色器,它只设置这些我可以像这样作为缓冲区访问的值?

void SetProjectionMatrix(float4x4 inputMatrix : MATRIX){
    Projection = inputMatrix;
}

请告诉我实现此目标的正确方法是什么。

最佳答案

首先,在您的着色器中,您需要将矩阵放入常量缓冲区中:

cbuffer CameraBuffer : register( b0 ) {
    float4x4 World;
    float4x4 View;
    float4x4 Projection;
}

如果您不声明常量缓冲区,它们会为您创建,但最好显式声明它们并按更新频率对它们进行分组。例如,将每帧更新的所有常量和仅设置一次的所有常量组合在一起。这允许您只更新需要更新的常量,而无需向 GPU 发送额外数据。

即使它们在这个 cbuffer 结构中,它们在您的着色器中仍然以相同的方式访问。

在您的 C++ 代码中,您需要声明一个类似的结构来存储您的矩阵:

struct CameraConstants {
    XMFLOAT4X4 world;
    XMFLOAT4X4 view;
    XMFLOAT4X4 projection;
};

注意 packing rules for constant variables 非常重要.此结构不会有问题,但在某些情况下,您可能需要向 C++ 结构添加额外的填充,以说明着色器 cbuffers 打包数据的事实,以便它不会跨越 16 字节边界,这是由于 16 字节的性质GPU 寄存器。

在初始化期间,您还需要创建一个常量缓冲区。该过程与顶点缓冲区相同,只是您需要使用以下标志来声明可由 CPU 写入的常量缓冲区:

cbDesc.Usage = D3D11_USAGE_DYNAMIC;
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

无论何时更新矩阵,都需要将它们上传到 GPU。为此,您将常量缓冲区映射到 CPU,并复制 CameraConstants 结构:

D3D11_MAPPED_SUBRESOURCE resource;
m_deviceContext->Map( cameraCbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource );
memcpy( resource.pData, cameraConstants, sizeof( CameraConstants ) );
m_deviceContext->Unmap( cameraCbuffer, 0 );

现在只需将常量缓冲区绑定(bind)到您的顶点着色器:

m_deviceContext->VSSetConstantBuffers( 0, 1, &cameraCbuffer );

请注意,第一个参数映射到您在着色器 cbuffer 声明中使用的寄存器(在本例中为 b0)。

还有一点,hlsl 中的矩阵默认是主要列。如果您的矩阵在 C++ 中是行主要的(可能),那么您需要在发送到 GPU 之前转置它们,或者在着色器中将您的矩阵声明为 row_major

查看 DirectX 示例以获得所有这些的一些源代码:https://code.msdn.microsoft.com/windowsdesktop/Direct3D-Tutorial-Win32-829979ef

关于c++ - 在 hlsl 着色器中设置全局参数的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26571743/

相关文章:

c++ - 如何最好地测试 Mutex 实现?

c++ - 网格面三角形的纵横比

c++ - 具有混合属性的烦人的类层次结构

ios - 位于相机 View 中心的 Scenekit 对象(Swift)

c++ - 写一个函数 sumVector : not returning a value

javascript - 有谁知道在哪里可以找到 carousel.us JavaScript 3D Carousel 的代码?开发者网站已关闭

c - 带阴影的快速 'ball' 像素光栅化例程

c++ - DX11 Compute Shader 只写入一个索引

silverlight - HLSL 色调变化算法

xna - 你如何编写一个什么都不做的顶点着色器?