Вопрос

Recently I decided to compress my vertex data to make rendering more efficient, and I came across a solution - using half (specifically, half4 and half2) instead of float for storing my vertex data. My vertex struct is given below:

[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);  
}  

And here is my vertex declaration:

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

        });

Everything works fine when I directly send my data as array of MyVertex to DrawUserPrimitives.
But when I decided to put all my data into VBO's to avoid excessive copying operations, all my mesh transformed into a pixel mess. I write my values as ushorts (SlimDX halfs have RawValue field for every component).
Here is what PIX says about my mesh: crazy numbers

And here is the same part in buffer viewer after specifying my layout (I'll show only one column, since they're pretty wide, hope you'll get the idea):
there is a nice numbers you have there
As you can see, my halfs is wrongly threated as floats. Changing float4 to half4 in the shader also doesn't help, seems like the issue is somewhere else. Is there another way to tell my GPU to use my vertex buffer as buffer of halfs and not as a buffer of floats?

UPD:
Here is my drawing code (shortened):

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);
        }
    }

And here is how this method is being called (the main part):

_eff.BeginPass(0);
GraphicsDevice.VertexDeclaration = vDecl;
renderer.Render(GraphicsDevice, camera, world);
_eff.EndPass();

I'm using D3D9 through SlimDX with C#.

Это было полезно?

Решение

I figured it out. I forgot to lock my buffer and call my VertexDeclaration initialization method. Such a shame for a programmer with 5 years of experience... Thanks, it works now :)

Другие советы

Usual graphics cards' pipelines are optimized to calculate the high bandwidth stuff with floats.

I don't think directx can handle halfs in vertexbuffers on the low level.

I'm backing up my speculation with the documentations of Device::CreateVertexBuffer and D3DFVF:

CreateVertexBuffer: The format is passed with the parameter FVF. Maybe when setting this to a non-fvf buffer it's possible to render the buffer with custom shaders (but I don't know if your framework would attempt to do that as it may be slower). If it's non-zero:

D3DFVF: All the available vertex formats are float only.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top