在 DirectX 11 中添加着色器的法线信息 - 法线在着色器中不可见

Adding normal information for the shader in DirectX 11 - normals not visible in shader?

本文关键字:DirectX 添加 信息      更新时间:2023-10-16

我想为着色器添加法线贴图信息。我使用 DirectX 11 C++ SDK 中的教程 5 作为基础。

着色器创建的代码是(我只是为了确保我已经发布了所有重要信息,但我认为只有D3D11_INPUT_ELEMENT_DESC布局[]很重要):

// Compile the vertex shader
ID3DBlob* pVSBlob = NULL;
HRESULT hr = CompileShaderFromFile( strToWchart(vertexShaderFileName), "VS", "vs_4_0", &pVSBlob );
// Create the vertex shader
hr = device->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &vertexShader );
if( FAILED( hr ) )
{   
pVSBlob->Release();
}

// Define the input layout
D3D11_INPUT_ELEMENT_DESC layout[] =
{
    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 12, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = ARRAYSIZE( layout );
// Create the input layout
hr = device->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(),
                                      pVSBlob->GetBufferSize(), &*vertexLayout );
pVSBlob->Release();
    // Set the input layout
context->IASetInputLayout( *vertexLayout );
// Compile the pixel shader
ID3DBlob* pPSBlob = NULL;
hr = CompileShaderFromFile( strToWchart(pixelShaderFileName), "PS", "ps_4_0", &pPSBlob );
// Create the pixel shader
hr = device->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &pixelShader );
pPSBlob->Release();
}

所以简单地D3D11_INPUT_ELEMENT_DESC我已将布局[]更改为(添加"正常"行):

D3D11_INPUT_ELEMENT_DESC layout[] =
{
    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 12, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};

比我在框创建方法中更改了几行:

// Create vertex buffer
SimpleVertex vertices[] =
{
    { XMFLOAT3(  - halfSize.getX(),  + halfSize.getY(),  - halfSize.getZ() ), XMFLOAT4( 0.0f, 0.0f, 1.0f, 1.0f ), XMFLOAT4( 0.0f, 0.0f, 1.0f, 1.0f ) },
    { XMFLOAT3(  + halfSize.getX(),  + halfSize.getY(),  - halfSize.getZ() ), XMFLOAT4( 0.0f, 1.0f, 0.0f, 1.0f ), XMFLOAT4( 0.0f, 1.0f, 1.0f, 1.0f ) },
    { XMFLOAT3(  + halfSize.getX(),  + halfSize.getY(),  + halfSize.getZ() ), XMFLOAT4( 0.0f, 1.0f, 1.0f, 1.0f ), XMFLOAT4( 0.0f, 0.0f, 1.0f, 1.0f ) },
    { XMFLOAT3(  - halfSize.getX(),  + halfSize.getY(),  + halfSize.getZ() ), XMFLOAT4( 1.0f, 0.0f, 0.0f, 1.0f ), XMFLOAT4( 0.0f, 0.0f, 1.0f, 1.0f ) },
    { XMFLOAT3(  - halfSize.getX(),  - halfSize.getY(),  - halfSize.getZ() ), XMFLOAT4( 1.0f, 0.0f, 1.0f, 1.0f ), XMFLOAT4( 0.0f, 1.0f, 1.0f, 1.0f ) },
    { XMFLOAT3(  + halfSize.getX(),  - halfSize.getY(),  - halfSize.getZ() ), XMFLOAT4( 1.0f, 1.0f, 0.0f, 1.0f ), XMFLOAT4( 0.0f, 0.0f, 1.0f, 1.0f ) },
    { XMFLOAT3(  + halfSize.getX(),  - halfSize.getY(),  + halfSize.getZ() ), XMFLOAT4( 1.0f, 1.0f, 1.0f, 1.0f ), XMFLOAT4( 1.0f, 0.0f, 1.0f, 0.0f ) },
    { XMFLOAT3(  - halfSize.getX(),  - halfSize.getY(),  + halfSize.getZ() ), XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ), XMFLOAT4( 0.0f, 0.0f, 1.0f, 1.0f ) },
};

所以所有行中的最后XMFLOAT4都是正常的(这些是错误的法线并不重要,现在我只想让它在顶点着色器中可见)。

我还更改了SimpleVertex:

struct SimpleVertex
{
    XMFLOAT3 Pos;
    XMFLOAT4 Color;
    XMFLOAT4 Normal;
};

还有我的着色器来检查法线是否存在:

cbuffer ConstantBuffer : register( b0 )
{
matrix World;
matrix View;
matrix Projection;
}
struct VS_INPUT
{
    float4 Pos : POSITION;
    float4 Color : COLOR;
float4 Normal : NORMAL; 
};
struct PS_INPUT
{
    float4 Pos : SV_POSITION;
    float4 Color : COLOR;
};
PS_INPUT VS( VS_INPUT input )
{
    PS_INPUT output = (PS_INPUT)0;

    output.Pos = mul( input.Pos, World );
    output.Pos = mul( output.Pos, View );
    output.Pos = mul( output.Pos, Projection );
output.Color = input.Normal; //just to know if I have a normals
    return output;
}
float4 PS( PS_INPUT input) : SV_Target
{
    return input.Color;
}

但效果只是一个黑匣子(即使有输出。颜色 = 输入。正常)。

那么,问题出在哪里呢?我必须更改其他内容才能在着色器中获取法线信息?

看起来您的D3D11_INPUT_ELEMENT_DESC数组与您的顶点数据不匹配。试试这个:

// Define the input layout
D3D11_INPUT_ELEMENT_DESC layout[] =
{
  { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  { "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};

法线的偏移量应包括"POSITION"(12 字节)和"COLOR"(16 字节,而不是 12)的偏移量。而且我不知道您为什么要为此设置输入槽。

我不知道

这是否是你的问题,但这里看起来有些不对劲:-

{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
 { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
 { "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 12, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; 

颜色 r32g32b32a32 类型的条目大小为 16 字节,但这似乎不正确,我希望最后一行的 24 是 28。另外,您将输入插槽设置为12,我不太确定为什么?