首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在hlsl着色器中设置全局参数的正确方法是什么?

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

Stack Overflow用户
提问于 2014-10-26 09:50:32
回答 1查看 3.7K关注 0票数 1

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

代码语言:javascript
复制
float4x4 World;
float4x4 View;
float4x4 Projection;

我在一个顶点着色器里使用它们:

代码语言:javascript
复制
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中设置这些全局值。相机什么时候动的?我是否应该创建另一个着色器,它将这些值设置为这样的缓冲区?

代码语言:javascript
复制
void SetProjectionMatrix(float4x4 inputMatrix : MATRIX){
    Projection = inputMatrix;
}

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-10-27 05:03:57

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

代码语言:javascript
复制
cbuffer CameraBuffer : register( b0 ) {
    float4x4 World;
    float4x4 View;
    float4x4 Projection;
}

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

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

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

代码语言:javascript
复制
struct CameraConstants {
    XMFLOAT4X4 world;
    XMFLOAT4X4 view;
    XMFLOAT4X4 projection;
};

照顾好常量变量的填充规则是非常重要的。这种结构没有任何问题,但在某些情况下,您可能需要在C++结构中添加额外的填充,以说明着色器cbuffers打包数据的事实,这样由于GPU寄存器的16字节性质,它不会跨越16字节的边界。

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

代码语言:javascript
复制
cbDesc.Usage = D3D11_USAGE_DYNAMIC;
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

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

代码语言:javascript
复制
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 );

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

代码语言:javascript
复制
m_deviceContext->VSSetConstantBuffers( 0, 1, &cameraCbuffer );

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

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

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

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26571743

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档