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

时间:2014-10-26 09:50:33

标签: 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;
}

请告诉我实现这一目标的正确方法。

1 个答案:

答案 0 :(得分:4)

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

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 );

现在只需将常量缓冲区绑定到顶点着色器:

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

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

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

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