有没有一种特定的方法可以将数组作为常量缓冲区传递给着色器?
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.
在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.