Jump to content
  • Advertisement
Sign in to follow this  
irreversible

How phat is your v%#!&x?

This topic is 1022 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

First off, I'm writing this as part of background research. For the first time I'm attempting to place some code in a general-use library and I want to come up with a dumbuser-compatible public interface for it. In short, what I need to do is serialize arbitrary vertex formats.

 

For instance I keep my data in a simple tightly packed std::vector-like structure:

 

VECTOR<vec3> vertices;

VECTOR<int32> indices;

 

which I can trivially parse with something generic like this:

 

template<typename V, typename I>

void SubmitVertexData(IN V* data, IN int32 numComponentsPerVertex, IN I* indices, IN int32 numVertices)

{

//pew-pew

}

 

SerializeVertexData(&vertices[0].c[0], 3, &indices[0], indices.size());

 

Now, while the above code supports most forms of tightly packed data that is already serialized, people tend to use all kinds of creative data structures for all kinds of fancy purposes. You know, things like lists. Since I'm forced to serialize the data down the line anyway and the whole purpose of this part of the library's interface is to be fast and only copy data while casting it into a simple internal base format, I want to cut out any proxy code that would need to be explicitly written by the user in order to invoke the library in the first place. In short I want to provide 3-4 general purpose functions that can parse a variety of data structures and formats. 

 

In addition to the above sample I have already covered interleaved formats with stride.

 

While this thread might make you scratch your head, there's a reason why I'm asking this: I'm writing a very light drop-in interface for a real-time vertex data debugger and I want it to work out of the box with as many formats as possible. The vertex data itself can have any base type that can be cast to a floating point format.

 

So yeah, do your worst - post your vertex definiton here! The ugliest one gets a cookie.

Edited by irreversible

Share this post


Link to post
Share on other sites
Advertisement

I guess you're not supporting interweaving data types?

What if someone's vertex format is:

struct Vertex
{
     float position[3];
     uint8_t color[4];
};

Anyway, mine is basically: (depends on what I'm drawing / what shader is being used)

//Going to separate VBOs.
std::vector<Vector2f> positions;
std::vector<TexCoords> texCoords;
std::vector<Inverts> inversions;
std::vector<Vector4f> colorations;

struct Inverts
{
    float invertDiffuse = 0.0f; //1.0 = true, 0.0 = false
    float invertMask = 0.0f;
    //float saturation = 0.0f;
    //float blur = 0.0f;
};

struct TexCoords
{
    vec2f diffuseCoord;
    vec2f maskCoord;
    //vec2f normalCoord;
    vec2f depthCoord;
    //vec2f glowCoord; 
};

Share this post


Link to post
Share on other sites

 

I guess you're not supporting interweaving data types?

What if someone's vertex format is:

struct Vertex
{
     float position[3];
     uint8_t color[4];
};

 

Correct me if I'm wrong, but this is just a simple case of stride, which is trivial to cover:

 

SerializeVertexData(&vertices[0].position[0], 3, stride = sizeof(Vertex));

 

EDIT: your use of the word colorations is a delight!

Edited by irreversible

Share this post


Link to post
Share on other sites

Yes, just a stride. Didn't see it in your code sample, so I assumed you missed it. But 'twas I who missed the part of your OP where you mentioned stride. ph34r.png

Re: Colorations, thanks. happy.png

 

[Edit:] Yea, I have the TexCoords separate so I can animate those separately. I forget why I made the colors, positions, and inversions separate though - they should probably be interleaved.

Share this post


Link to post
Share on other sites

My current library supports arbitrary arrangements of components, split across arbitrary vertex buffers. Generally, one wants to interleave as much data as possible, but occasionally one wants to animate positions and normals but not texcoords... or share the same set of texture coordinates across multiple tiles in a terrain system.

 

Each mesh effectively has a set of mappings from VertexBuffer -> (type, component count, byte offset, binding semantic), which are stored in a flat array, sorted by VertexBuffer.

 

Is that too generic? Maybe. I don't use the full expressiveness of the system very often. But it's pretty straightforward to adapt other systems into.

Share this post


Link to post
Share on other sites
Yeah mine are arbitrary too.
Here's some example vertex layouts used in my current project: http://pastebin.com/5k0UV1fP

Note that it's common to use two "streams" of data (two buffers, or two offsets within the one buffer), and in the general case there could well be thirty streams...

Share this post


Link to post
Share on other sites

Arbitrary is the way to go.

 

For example in Ogre we use 16-bit half for position, short4 for QTangents (Quaternion), half for UVs. uchar4/short4/float4 for blend weights, uchar4 non normalized for blend indices.

 

RenderDoc solves this problem very easily by letting you define the arrangement you want.

e.g. type

float4,ushort2,uchar4

And the data is reinterpreted. I suggest you look at RenderDoc because it really nailed it.

 

Your first mistake is assuming people will use a vertex buffer for storing vertex data.

Your second mistake is assuming casting to float is valid. For example, a bitmask will often produce a NaN. The only helpful visualization in a debugger is a decimal, hexadecimal, or binary representation.

Edited by Matias Goldberg

Share this post


Link to post
Share on other sites

16 byte per vert

 

10/10/10/2 for position and 2 bits that aren't being used atm

10/10/10/2 for normal encoded into x/y. The last 12 bits aren't used atm

 8/8/8/8 - albedo in first 3, shadow value in last

 8/8/8/8 - roughness, spec, and ao. Last is unused.

Edited by Triangles-PCT

Share this post


Link to post
Share on other sites

I store my meshes like this:

VertexDecl {
 string semantic;
 Type type; //float int float3 float4 ect.
 int byteOffset; // from the begining of the element.
}

struct MeshDesc {
 void* vertexBufferData;
 size_t byteOffsetInVertexBufferData;
 std::vector<VertexDecl> vertDecl;
 int strideSize;
};

struct Mesh
{
 vector<MeshDesc> descs;
}

And this is how it "rolls" basically as a pseudo code. And when I know what the exact vertex strcture is, I put few asserts and cast the void* to "MyVertexStruct*".

Edited by imoogiBG

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!