2

DirectX を使用して MS3D モデルを表示するプログラムを作成していますが、残念ながら結果は画面に何も表示されません。Visual Studio 13 のグラフィックス デバッガーを使用すると、下の図に示すように、ピクセル シェーダーがパイプラインにないことに気付きました。

画像

これは私のピクセル シェーダー ソース コードです。

 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 シェーダーがパイプラインから欠落している理由は何ですか。その結果、空の画面が表示される可能性があります。

4

2 に答える 2

3

他の回答に加えて、一定のバッファー構成がこの問題の原因である可能性があります。私の場合、パイプラインにピクセル シェーダーがありませんでしたが、頂点シェーダーも頂点を正しく変換していませんでした。調べたところ、定数バッファーの上部にあるブール値がデータのずれを引き起こしているため、ワールド マトリックスの値が正しくないことが判明しました。HLSL は、データを 16 バイト境界にパックします。これは、4 つのコンポーネントを持つベクターと呼ばれます。boolean は float と同じ 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 つのコンポーネントだけシフトされ、ワー​​ルド行列 (およびそれに続く他の行列) がずれます。おそらく他のデータ)。

2 つの可能な解決策:

  1. ブール値を構造体の最後に移動します。私はこれをしました、そしてそれはうまくいきました。
  2. ワールド マトリックスとブール値の間に3 コンポーネント サイズのパディング変数を追加します。C++ 構造体に XMFLOAT3 を追加し、HLSL に float3 を追加して、これを試しました。これもうまくいきました。

簡単に言うと、HLSL パッキングに注意してください。

EDIT:ブール値を除くすべての変数が正しい値を持っていたので、これらのメソッドが機能すると思ったとき。当時はブールを使用していなかったので、それも問題ないと思いました。そうではないことがわかりました。

HLSL bool と c++ bool はサイズが異なります。HLSL bool は 4 バイトですが、c++ bool は実装定義です (たとえば、私のマシンでは 1 バイト)。とにかく、それらは異なる可能性が高く、問題を引き起こします。

Windows BOOL 型、または int や uint などの適切なサイズの別の値を使用してください。

https://gamedev.stackexchange.com/a/22605をご覧ください。

また、ここの最後から 2 番目の投稿では、状況が明確に説明されています (このリンクは、上記の gamedev リンクの回答でも参照されています)。

梱包がまだ問題なので注意してください。BOOL や uint などを使用しても、以前のように上記の構造体の先頭に配置すると、定数バッファーに正しくない値が取得されます。そのため、定数バッファーを使用する場合は、これらの問題 (データの配置とブール値の問題) の両方を考慮してください。

于 2015-10-20T22:26:44.900 に答える
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;
于 2014-04-12T15:17:24.460 に答える