有没有一种特定的方法可以将数组作为常量缓冲区传递给着色器?

Is there a specific way to pass an array as a constant buffer to the shader?

在c++中,数组中有一个值,当我将它传递给着色器时,数据全为0。有没有具体的方法将数组传递给着色器?

这是我设置常量缓冲区的代码

    vector<XMFLOAT4X4> finalTransforms = Animator->GetTransforms(_timeDelta);

    BoneTransformBuffer.SetData(GraphicDev->GetDeviceContext(), finalTransforms);
    auto Transform = BoneTransformBuffer.GetBuffer();
    GraphicDev->GetDeviceContext()->VSSetConstantBuffers(1, 1, &Transform);

这是我在着色器中的常量缓冲区

cbuffer cbSkinned : register(b1)
{
    float4x4 BoneTransforms[96];
};

您的代码片段缺少很多关于您的类型和支持代码的信息,但我的第一个猜测是您应该使用:

BoneTransformBuffer.SetData(GraphicDev->GetDeviceContext(), finalTransforms.data());

此外,这一行 vector<XMFLOAT4X4> finalTransforms = Animator->GetTransforms(_timeDelta); 正在额外复制所有数据,除非 GetTransforms 依赖于 return-优化。

皮肤

请注意,对于蒙皮,您通常不需要为每个骨骼使用完整的 4x4 矩阵。蒙皮动画几乎总是使用仿射变换(平移、缩放和旋转),因此您在常量缓冲区中浪费了 25% 的 space。

改为使用:

struct SkinnedConstants
{
    XMVECTOR bones[96][3];
};
cbuffer cbSkinned : register(b1)
{
    float4x3 BoneTransforms[96];
};

然后你可以使用类似这样的东西来设置骨骼数据:

    for (size_t i = 0; i < count; i++)
    {
#if DIRECTX_MATH_VERSION >= 313
        XMStoreFloat3x4A(reinterpret_cast<XMFLOAT3X4A*>(&boneConstant[i]), value[i]);
#else
        // Xbox One XDK has an older version of DirectXMath
        XMMATRIX boneMatrix = XMMatrixTranspose(value[i]);

        boneConstant[i][0] = boneMatrix.r[0];
        boneConstant[i][1] = boneMatrix.r[1];
        boneConstant[i][2] = boneMatrix.r[2];
#endif
    }

HLSL 代码类似于:

float3 Skin(inout VSInputNmTxWeights vin, float3 normal, uniform int boneCount)
{
    float4x3 skinning = 0;

    [unroll]
    for (int i = 0; i < boneCount; i++)
    {
        skinning += Bones[vin.Indices[i]] * vin.Weights[i];
    }

    vin.Position.xyz = mul(vin.Position, skinning);
    return mul(normal, (float3x3)skinning);
}

See XNA Game Studio Stock Effects and DirectX Tool Kit for DX11 / DX12.