2014-01-18 40 views
2

我在写一个使用DirectX显示MS3D模型的程序,不幸的是,结果在屏幕上什么也没有显示。 当我使用的图形调试器从Visual Studio 13,我注意到,像素着色器从管线缺少,因为它是在下面的图片所示流水线中的DirectX11像素着色器丢失

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

正如我从图形调试器得知的那样,所有的图形事件都是正确的。我列出了以下重要事件,这可能是与像素着色器:

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。没有什么不对。 我的问题是pixple shader从pipleline中丢失的原因是什么,这反过来可能导致空白屏幕。

+0

你最终弄清楚了这个问题吗?我有同样的问题(PS在管道阶段丢失,但在直接上下文的对象视图中处于活动状态,因此它不是http://msdn.microsoft.com/zh-cn/library/jj191650中描述的问题的.aspx)。当然,图像是黑色的... – Christoph

+0

相同的确切问题,验证RS状态和从VS输出。我确实注意到通过RSSetViewports被调用的事件,draw调用的视口是'Not Set'。我仍在调查这一点。 –

+0

好的,对我来说,它发生是因为我乐观地将视口的最大深度设置为100.0f,而最多应该是1.0f。尽管我在光栅化器中禁用了深度裁剪,但是这可以防止RSSetViewports根本设置视口,并且不会引发错误。检查图形调试器是否实际设置了设备上下文中的视口。 –

回答

1

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

在我的情况下,像素着色器被正确绑定(请参阅http://msdn.microsoft.com/en-us/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; 
2

添加到其他答案,恒定的缓冲区组织可能是造成此问题的原因。在我的情况下,像素着色器从管线中丢失,但顶点着色器也没有正确转换顶点。在检查时发现世界矩阵的值不正确,因为常量缓冲区顶部的布尔值导致数据未对齐。 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组件大小的填充变量。 我试图通过在C++结构中添加一个XMFLOAT3和在HLSL中添加一个float3。这也工作。

长话短说,注意HLSL包装。

编辑:当时我以为这些方法的工作,因为除了布尔值之外的所有变量都有正确的值。我当时没有使用布尔,所以我认为这也没问题。原来不是。

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

可以使用Windows BOOL类型或其他适当大小的值,例如int或uint。请参阅https://gamedev.stackexchange.com/a/22605

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

请小心,因为包装仍然是一个问题。即使你使用BOOL或uint或其他类型,如果你像前面一样将它放置在上述结构的开头,你将在常量缓冲区中得到不正确的值。因此,在处理常量缓冲区时要考虑这两个问题(数据对齐和布尔问题)。