最近我决定压缩我的顶点数据以提高渲染效率,我遇到了一个解决方案 - 使用 half (特别是half4和half2)而不是 float 来存储我的顶点数据。我的顶点结构如下:
[StructLayout(LayoutKind.Sequential)]
public struct MyVertex
{
public Half4 Position; //8 bytes
public Half4 Normal; //8 bytes
public Half2 UVW; //4 bytes
public Half4 TextureID; //8 bytes
public Half4 BlendFactor; //8 bytes
public const int SizeInBytes = (2 * 4) * 4 + (2 * 2);
}
这是我的顶点声明:
MyVertexDecl = new VertexDeclaration(device,
new VertexElement[6]
{
new VertexElement(0, 0, DeclarationType.HalfFour, DeclarationMethod.Default, DeclarationUsage.Position, 0),
new VertexElement(0, 8, DeclarationType.HalfFour, DeclarationMethod.Default, DeclarationUsage.Normal, 0),
new VertexElement(0, 16, DeclarationType.HalfTwo, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 0),
new VertexElement(0, 20, DeclarationType.HalfFour, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 1),
new VertexElement(0, 28, DeclarationType.HalfFour, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 2),
VertexElement.VertexDeclarationEnd
});
当我将数据作为 MyVertex 数组直接发送到 DrawUserPrimitives 时,一切正常。
但是当我决定将所有数据放入 VBO 以避免过度复制操作时,我所有的网格都变成了像素混乱。我将我的值写为 ushorts(SlimDX halfs 的每个组件都有 RawValue 字段)。
以下是 PIX 对我的网格的评价:
这是指定布局后缓冲区查看器中的相同部分(我只显示一列,因为它们很宽,希望你能明白)
:看,我的一半被错误地威胁为漂浮物。在着色器中将 float4 更改为 half4 也无济于事,似乎问题出在其他地方。是否有另一种方法告诉我的 GPU 使用我的顶点缓冲区作为半缓冲区而不是作为浮点缓冲区?
UPD:
这是我的绘图代码(缩短):
public void Render(GraphicsDevice device, ICamera camera, MyModel model)
{
//there are some SetValue calls
model.Effect.CommitChanges();
foreach (D3D9.VertexBuffer buf in model.Meshes)
{
device.SetStreamSource(0, buf, 0, MyVertex.SizeInBytes);
device.DrawPrimitives(D3D9.PrimitiveType.TriangleList, 0, mesh.VertexCount);
}
}
这是调用此方法的方式(主要部分):
_eff.BeginPass(0);
GraphicsDevice.VertexDeclaration = vDecl;
renderer.Render(GraphicsDevice, camera, world);
_eff.EndPass();
我通过 SlimDX 和 C# 使用 D3D9。