【问题标题】:DirectX - halfs instead of floats in vertex bufferDirectX - 顶点缓冲区中的半数而不是浮点数
【发布时间】:2013-06-08 16:25:00
【问题描述】:

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

【问题讨论】:

  • 你能显示你的代码 sn-p 来填充缓冲区吗?
  • @Gnietschow 当然,这里是 - pastebin.com/YzcnUc8r
  • 嗯,没有看到任何错误。你的绘图代码呢?愚蠢的问题:你记得在draw call之前设置顶点声明吗?
  • @Gnietschow 听起来我当时在某个地方犯了一个愚蠢的错误。我已经用部分绘图代码更新了我的帖子。感谢您的帮助!
  • 那很好:),但不幸的是我不知道为什么它不起作用。最后一个猜测:在你的填充代码中你使用data.indices.Count(),不应该是顶点的计数吗?你会解锁缓冲区吗?

标签: c# directx slimdx vertex-buffer


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

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

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

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

    【讨论】:

    • 他使用的是顶点声明而不是 FVF,所以应该可以使用一半,例如在文档msdn.microsoft.com/en-us/library/windows/desktop/… 中有一个声明类型D3DDECLTYPE_FLOAT16_4
    • @Gnietschow 是的,你是对的 - 我无法让它与我的顶点缓冲区一起工作的问题。我的 GPU 支持 D3DTDELTYPE_FLOAT_16_4 但看起来他不知道如何解释我的缓冲区,或者我只是将我的参数发送到错误的地方,或者我用错误的值填充我的缓冲区......据我可以从 PIX 看到输出,GPU 只是将我的缓冲区解释为浮点数,忽略我的 decltype。如果需要,我可以向您展示更多代码。任何帮助将不胜感激:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    相关资源
    最近更新 更多