繁体   English   中英

流水线中缺少DirectX11像素着色器

[英]DirectX11 pixel shader in pipeline is missing

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

图片

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

 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所知,所有图形事件都是正确的。 我在以下重要事件中列出了这些事件,这些事件可能与Pixel Shader有关:

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。 没有什么不对。 我的问题是pipleline缺少pixex着色器的原因是什么,而这又可能导致屏幕空白。

除其他答案外,恒定的缓冲区组织可能是导致此问题的原因。 在我的情况下,流水线缺少像素着色器,但顶点着色器未正确转换顶点。 通过检查发现,世界矩阵的值不正确,因为常量缓冲区顶部的布尔值导致数据未对齐。 HLSL将数据打包到16个字节的边界中,这就是所谓的具有4个分量的向量 布尔值是4个字节,与浮点数相同。

cbuffer cbPerObject : register( b1 )
{
    bool gUseTexture ;

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

因此,在上面的常量缓冲区中,世界矩阵第一行的布尔值+前3个分量被映射到第一个向量 ,这将导致所有内容都移位3个分量,从而使世界矩阵(以及之后和可能还有其他数据)。

两种可能的解决方案:

  1. 将布尔值移到结构的末尾。 我做到了,它奏效了。
  2. 在世界矩阵和布尔值之间添加3分量大小的padding变量。 我通过在c ++结构中添加XMFLOAT3和在HLSL中添加float3进行了尝试。 这也起作用。

长话短说,注意HLSL包装。

编辑:当时我认为这些方法有效,因为除布尔值以外的所有变量都有正确的值。 当时我没有使用bool,所以我也认为这很好。 事实并非如此。

HLSL布尔和c ++布尔具有不同的大小。 HLSL bool是4个字节,而c ++ bool是实现定义的(例如,在我的机器上是1个字节)。 无论如何,它们很可能会有所不同,并且会引起问题。

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

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

同样, 这里的倒数第二篇文章也清楚地说明了这种情况(该链接也在上面的gamedev链接的答案中进行了引用)。

不过要当心,因为打包仍然是一个问题。 即使使用BOOL或uint或其他任何方法,如果像以前一样将其放在上述结构的开头,也会在常量缓冲区中获得错误的值。 因此,在使用常量缓冲区时,请同时考虑这两个问题(数据对齐和布尔问题)。

正如我在评论中写道,我有一个类似的问题。

就我而言,像素着色器已正确绑定(请参阅http://msdn.microsoft.com/zh-cn/library/jj191650.aspx )。 此外,我通过调试顶点着色器来确保转换的结果应该是可见的,因此应该生成可见的片段。

在这种情况下(看起来与您描述的相同),请确保光栅化器状态正确。 您可能要检查它是否已实际设置(使用即时上下文的图形对象视图)以及它是否允许您的几何图形通过。 出于调试目的,我发现禁用背面剔除很有帮助。 我用

D3D11_RASTERIZER_DESC rasterDesc;
ZeroMemory(&rasterDesc, sizeof(rasterDesc));
rasterDesc.CullMode = D3D11_CULL_MODE::D3D11_CULL_NONE;
rasterDesc.FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM