2014-01-18 70 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或其他類型,如果你像前面一樣將它放置在上述結構的開頭,你將在常量緩衝區中得到不正確的值。因此,在處理常量緩衝區時要考慮這兩個問題(數據對齊和布爾問題)。