4

最近我决定压缩我的顶点数据以提高渲染效率,我遇到了一个解决方案 - 使用 half (特别是half4half2)而不是 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。

4

2 回答 2

1

我想到了。我忘记锁定缓冲区并调用 VertexDeclaration 初始化方法。对于一个有 5 年经验的程序员来说真是太可惜了……谢谢,它现在可以工作了 :)

于 2013-06-21T15:47:32.387 回答
0

通常显卡的管道经过优化,可以使用浮点数计算高带宽的东西。

我不认为directx 可以在低级别处理顶点缓冲区中的一半。

我用 Device::CreateVertexBuffer 和 D3DFVF 的文档来支持我的推测:

CreateVertexBuffer:格式与参数 FVF 一起传递。也许将其设置为非 fvf 缓冲区时,可以使用自定义着色器渲染缓冲区(但我不知道您的框架是否会尝试这样做,因为它可能会更慢)。如果它不为零:

D3DFVF:所有可用的顶点格式都是浮点数。

于 2013-06-08T16:59:44.993 回答