【问题标题】:Shader does not get Vertex data except position, texcoord, normal除了位置、纹理坐标、法线之外,Shader 不获取顶点数据
【发布时间】:2021-10-04 05:20:15
【问题描述】:

我想读取骨骼的重量,但着色器无法读取数据

这是我的顶点类型

struct SkinnedMesh
{

XMFLOAT3 Position;
XMFLOAT2 Texture;
XMFLOAT3 Normal;
XMFLOAT3 Weight;
UINT BoneIndices[4];
};

这是初始化着色器描述

// Create the vertex input layout description.
polygonLayout[0].SemanticName = "POSITION";
polygonLayout[0].SemanticIndex = 0;
polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
polygonLayout[0].InputSlot = 0;
polygonLayout[0].AlignedByteOffset = 0;
polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[0].InstanceDataStepRate = 0;

polygonLayout[1].SemanticName = "TEXCOORD";
polygonLayout[1].SemanticIndex = 0;
polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT;
polygonLayout[1].InputSlot = 0;
polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[1].InstanceDataStepRate = 0;

polygonLayout[2].SemanticName = "NORMAL";
polygonLayout[2].SemanticIndex = 0;
polygonLayout[2].Format = DXGI_FORMAT_R32G32B32_FLOAT;
polygonLayout[2].InputSlot = 0;
polygonLayout[2].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[2].InstanceDataStepRate = 0;

polygonLayout[3].SemanticName = "BLENDWEIGHT";
polygonLayout[3].SemanticIndex = 0;
polygonLayout[3].Format = DXGI_FORMAT_R32G32B32_FLOAT;
polygonLayout[3].InputSlot = 0;
polygonLayout[3].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[3].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[3].InstanceDataStepRate = 0;

polygonLayout[4].SemanticName = "BLENDINDICES";
polygonLayout[4].SemanticIndex = 0;
polygonLayout[4].Format = DXGI_FORMAT_R32G32B32A32_UINT;
polygonLayout[4].InputSlot = 0;
polygonLayout[4].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[4].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[4].InstanceDataStepRate = 0;

numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);

// Create the vertex input layout.8
if (FAILED(_Device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), &Layout)))
{
    MSG_BOX("Failed to create vertex input layout.");
    return E_FAIL;
}
return S_OK;

这是 hlsl 代码

struct SkinnedInput
{
    float3 Position : POSITION;   
    float2 Tex : TEXCOORD;          
    float3 Normal : NORMAL;
    float4 Weights : WEIGHT;
    uint4 BoneIndices : BLENDINDICES;  
};

struct SkinnedOutput
{
    float4 Position : SV_POSITION;
    float2 Tex : TEXCOORD;
    float3 Normal : NORMAL;
};

SkinnedOutput main(SkinnedInput _Input)
{
    SkinnedOutput Out = (SkinnedOutput) 0;

    float weight[4];
    //weight[0] = _Input.Weights.x;
    //weight[1] = _Input.Weights.y;
    //weight[2] = _Input.Weights.z;
    //weight[3] = _Input.Weights.w;

    Out.Position = mul(float4(_Input.Position, 1.f), WorldMatrix);
    Out.Position = mul(Out.Position, ViewMatrix);
    Out.Position = mul(Out.Position, ProjectionMatrix);

    Out.Tex = _Input.Tex;

    Out.Normal = normalize(mul(float4(_Input.Normal, 0.f), WorldMatrix));

    
    return Out;

}

当我调试 hlsl 时,权重和骨骼索引中没有数据。 除了weights和boneindicies之外,我读过int值,但是读不出来

即使我更改数据顺序并读取它,也只会读取位置、texcoord 和 normal

有人知道吗?

我更改了结构和布局 decs

struct SkinnedMesh
{
    XMFLOAT3 Position;
    XMFLOAT2 Texture;
    XMFLOAT3 Normal;
    XMFLOAT4 Weight;
    XMUINT4 BoneIndices;
};

D3D11_INPUT_ELEMENT_DESC polygonLayout[] =
{
    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "BLENDWEIGHT", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "BLENDINDICES", 0, DXGI_FORMAT_R32G32B32A32_UINT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 } };

但结果是一样的..

【问题讨论】:

  • Position 在着色器中是一个 float4,在 C/C++ 中是一个 float3。此外,着色器中的 uint4 是 32 位的,而您在 C/C++ 中定义了一个 4 x 32 位的数组。
  • 我改了,结果还是一样的T^T
  • Weight 应该可以工作,但 BoneIndices 仍然不行。仔细阅读我之前的评论。
  • 我理解您的评论,即数据类型的大小应该适合 hlsl 和 c/c++ 之间的大小。但是我不知道怎么回事,因为重量仍然没有值

标签: shader directx-11


【解决方案1】:

这是一个编译器/运行时优化的案例。

由于在着色器中根本不使用混合权重,因此最终不会获取数据。

要正确测试它,您可以制作如下内容:

struct SkinnedOutput
{
    float4 Position : SV_POSITION;
    float2 Tex : TEXCOORD;
    float3 Normal : NORMAL;
    float4 Weights : WEIGHT;
};

并确保分配它:

 Out.Weights = _Input.Weights;

检查着色器反汇编时可见,您的输入声明是:

// Input signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// POSITION                 0   xyz         0     NONE   float   xyz 
// TEXCOORD                 0   xy          1     NONE   float   xy  
// NORMAL                   0   xyz         2     NONE   float   xyz 
// WEIGHT                   0   xyzw        3     NONE   float       
// BLENDINDICES             0   xyzw        4     NONE    uint  

注意 used 标志是空的,所以当你检查变量声明时:

vs_5_0
dcl_globalFlags refactoringAllowed
dcl_constantbuffer CB0[12], immediateIndexed
dcl_input v0.xyz
dcl_input v1.xy
dcl_input v2.xyz
dcl_output_siv o0.xyzw, position
dcl_output o1.xy
dcl_output o2.xyz
dcl_temps 2

可以看到shader只声明了v0(位置)、v1(uv)、v2(texcoords),未使用的根本没有声明。

请注意,编译器会非常积极地删除未使用的代码,因此即使您取消注释:

float weight[4];
weight[0] = _Input.Weights.x;
weight[1] = _Input.Weights.y;
weight[2] = _Input.Weights.z;
weight[3] = _Input.Weights.w;

但是权重不会写入输出,它也会被移除。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-24
    • 1970-01-01
    相关资源
    最近更新 更多