gpt4 book ai didi

c++ - 管道中的 DirectX11 像素着色器丢失

转载 作者:搜寻专家 更新时间:2023-10-31 01:06:13 26 4
gpt4 key购买 nike

我正在编写一个使用 DirectX 显示 MS3D 模型的程序,不幸的是,结果在屏幕上什么也没有显示。当我使用 Visual Studio 13 中的图形调试器时,我注意到管道中缺少像素着色器,如下图所示

image

这是我的像素着色器源代码:

 cbuffer SkinningTransforms
{
matrix WorldMatrix;
matrix ViewProjMatrix;
};
//--------------------------------------------------------------------------------
// Inter-stage structures
//--------------------------------------------------------------------------------
struct VS_INPUT
{
float3 position : POSITION;
int4 bone : BONEID;
float4 weights : BONEWEIGHT;
float3 normal : NORMAL;
float3 tangent : TANGENT;
float2 tex : TEXCOORD;
};
//--------------------------------------------------------------------------------
struct VS_OUTPUT
{
float4 position : SV_Position;
float3 normal : NORMAL;
float3 light : LIGHT;
float2 tex : TEXCOORDS;
};

Texture2D ColorTexture : register( t0 );
SamplerState LinearSampler : register( s0 );

//--------------------------------------------------------------------------------
VS_OUTPUT VSMAIN( in VS_INPUT input )
{
VS_OUTPUT output;
//Transform vertex and pass them to the pixel shader
return output;
}

//--------------------------------------------------------------------------------
float4 PSMAIN( in VS_OUTPUT input ) : SV_Target
{
// Calculate the lighting
float3 n = normalize( input.normal );
float3 l = normalize( input.light );


float4 texColor = ColorTexture.Sample( LinearSampler, input.tex );

float4 color = texColor * (max(dot(n,l),0) + 0.05f );
return( color );
}

正如我从 Graphics Debugger 了解到的那样,所有的图形事件都是正确的。我在下面列出了可能与像素着色器有关的重要事件:

106:(obj:4) ID3D11Device::CreateDepthStencilView(obj:24,NULL,obj:25)*
108:(obj:5) ID3D11DeviceContext::OMSetRenderTargets(8,{obj:1,NULL,NULL,NULL,NULL,NULL,NULL,NULL},obj:25)*
109:(obj:5) ID3D11DeviceContext::ClearRenderTargetView(obj:1,addr:21)*
111:(obj:5) ID3D11DeviceContext::ClearDepthStencilView(obj:25,1,1.000f,0)*
119:(obj:4) ID3D11Device::CreateSamplerState(addr:24,obj:27)*
134:(obj:4) ID3D11Device::CreatePixelShader(addr:27,21056,NULL,obj:30)*
135:CreateObject(D3D11 Pixel Shader,obj:30)
136:(obj:5) ID3D11DeviceContext::PSSetShader(obj:30,NULL,0)*
137:(obj:5) ID3D11DeviceContext::PSSetSamplers(0,1,{obj:27})*
139:(obj:4) ID3D11Device::CreateTexture2D(addr:28,addr:5,obj:31)*
140:CreateObject(D3D11 Texture2D,obj:31)
142:(obj:4) ID3D11Device::CreateShaderResourceView(obj:31,NULL,obj:32)*
143:CreateObject(D3D11 Shader Resource View,obj:32)
144:(obj:5) ID3D11DeviceContext::PSSetShaderResources(0,1,{obj:32})*
146:(obj:4) ID3D11Device::CreateRasterizerState(addr:29,obj:33)*
147:CreateObject(D3D11 Rasterizer State,obj:33)
152:(obj:5) ID3D11DeviceContext::RSSetState(obj:33)*
154:(obj:5) ID3D11DeviceContext::RSSetViewports(1,addr:30)*
156:(obj:4) ID3D11Device::CreateBlendState(addr:11,obj:34)*
157:CreateObject(D3D11 Blend State,obj:34)
159:(obj:5) ID3D11DeviceContext::OMSetBlendState(obj:34,addr:31,-1)*
162:(obj:4) ID3D11Device::CreateDepthStencilState(addr:32,obj:35)*
163:CreateObject(D3D11 Depth-Stencil State,obj:35)
165:(obj:5) ID3D11DeviceContext::OMSetDepthStencilState(obj:35,0)*

我调试了上面列表中的所有函数,它们都返回 OK。没有什么不对。我的问题是 pixex 着色器从 pipleline 中丢失的原因是什么,这反过来可能导致空屏幕。

最佳答案

添加到其他答案中,常量缓冲区组织可能是导致此问题的原因。在我的例子中,管道中缺少像素着色器,而且顶点着色器也没有正确转换顶点。经过检查,发现世界矩阵的值不正确,因为常量缓冲区顶部的 bool 值导致数据未对齐。 HLSL 将数据打包到 16 字节的边界中,这些边界称为 vectors,具有 4 个分量。 bool 值是 4 个字节,与 float 相同。

cbuffer cbPerObject : register( b1 )
{
bool gUseTexture ;

row_major float4x4 gWorld ;
row_major float4x4 gWorldInvTranspose ;
row_major float4x4 gWorldViewProj ;
row_major float4x4 gTexTransform ;
Material gMaterial ;
} ;

所以在上面的常量缓冲区中, bool 值 + 世界矩阵第一行的前 3 个分量被映射到第一个 vector ,这导致一切移动 3 个分量,错位世界矩阵(以及后面的其他矩阵和可能的其他数据)。

两种可能的解决方案:

  1. 将 bool 值移动到结构的末尾。我这样做了,它奏效了。
  2. 在世界矩阵和 bool 值之间添加一个 3 分量大小的 padding 变量。我通过在 c++ 结构中添加一个 XMFLOAT3 并在 HLSL 中添加一个 float3 来尝试这个。这也奏效了。

长话短说,注意HLSL打包。

编辑:当时我认为这些方法有效,因为除了 bool 值之外的所有变量都有正确的值。当时我没有使用 bool,所以我认为这也很好。事实证明不是。

HLSL bools 和 c++ bools 有不同的大小。 HLSL bools 是 4 个字节,而 c++ bools 是实现定义的(例如在我的机器上是 1 个字节)。无论如何,它们很可能会有所不同,这会导致问题。

使用 Windows BOOL 类型或其他适当大小的值,如 int 或 uint。

看看https://gamedev.stackexchange.com/a/22605 .

也是倒数第二个帖子here清楚地解释了情况(此链接也在上面 gamedev 链接的答案中引用)。

但要小心,因为包装仍然是一个问题。即使您使用 BOOL 或 uint 或其他任何东西,如果您像以前一样将它放在上述结构的开头,您将在常量缓冲区中得到不正确的值。因此,在使用常量缓冲区时,请考虑这两个问题(数据对齐和 bool 问题)。

关于c++ - 管道中的 DirectX11 像素着色器丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21206196/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com