D3D11着色器仅能读取顶点位置/纹理/法线,无法读取骨骼权重与索引求助
故障核心原因
- 第一是HLSL顶点输入语义与C++输入布局不匹配:你在C++的输入布局中为骨骼权重指定的语义名是
BLENDWEIGHT,但HLSL的SkinnedInput结构里权重字段用的是WEIGHT语义,两者名称完全不一致,D3D11无法将顶点缓冲区的权重数据映射到着色器输入变量,导致读到的是未初始化的无效值。 - 第二是存在潜在的C结构体内存对齐问题:你没有显式指定C顶点结构体的对齐规则,不同编译器/编译选项可能会在结构体成员之间插入填充字节,导致
D3D11_APPEND_ALIGNED_ELEMENT计算的偏移量和实际结构体成员偏移不匹配,最终数据读取错位。 - 可选排查项:顶点缓冲区绑定的步长(stride)设置错误,如果调用
IASetVertexBuffers时传入的步长不等于sizeof(SkinnedMesh),也会导致顶点数据读取错位,蒙皮相关字段无法拿到正确值。
修复步骤
- 修正HLSL的权重语义,将
SkinnedInput里的权重字段语义改为和输入布局一致的BLENDWEIGHT:
struct SkinnedInput { float3 Position : POSITION; float2 Tex : TEXCOORD; float3 Normal : NORMAL; float4 Weights : BLENDWEIGHT; // 此处将WEIGHT修改为BLENDWEIGHT uint4 BoneIndices : BLENDINDICES; };
- 显式指定C++顶点结构体的对齐,避免编译器插入填充字节,修改后的顶点结构体定义如下:
#pragma pack(push, 16) // 按16字节对齐,匹配HLSL默认结构体对齐规则 struct SkinnedMesh { XMFLOAT3 Position; XMFLOAT2 Texture; XMFLOAT3 Normal; XMFLOAT4 Weight; XMUINT4 BoneIndices; }; #pragma pack(pop)
- 检查
IASetVertexBuffers调用,确保传入的顶点步长正确:
UINT stride = sizeof(SkinnedMesh); UINT offset = 0; _pd3dDeviceContext->IASetVertexBuffers(0, 1, &pVertexBuffer, &stride, &offset);
- 可选优化:确保骨骼权重的4个分量和为1,避免蒙皮计算出现异常拉伸。
内容的提问来源于stack exchange,提问作者문형준
相关产品推荐
相关产品推荐

