Skip to main content
gamedev.net
🔒 Locked

Non-interleaved data

Started by outRider 17 replies 950+ views
Original Post
outRider
outRider
I haven''t used D3D/DD since DX7 so forgive me if this question hurts. I''m using D3D8 currently. I''ve noticed that when you create vertex buffers your data must be interleaved, based on the FVF you''re using. In OGL I can specify seperate vertex, color, texcoord, etc buffers instead of having the vertex/color/texcoord data together as D3D seems to require. The problem is all my old code, even though a lot of it isn''t tied to GL directly, has data seperated like this. My mesh class has seperate buffers for vertex, color, etc data. Is there a way I can use this in D3D or am I stuck having to rewrite my loaders so they load data into a single buffer or at least shuffle stuff around in memory at runtime (painfully inefficient)? ------------ - outRider -
RhoneRanger
RhoneRanger
Start by following the tuts in the DirectX sdk docu.

All your hard work is not at a loss because the DrawPrimitive and DrawIndexedPrimitive functions are basically the same.

You just now have control over the vertex types and you have more control on how to manage them.

For example, DirectX7 had D3DLVERTEX as a type.

in DX8, you need to declare this.

struct CustomVertex
{
D3DXVECTOR3 Position;
DWORD Color;
D3DXVECTOR2 TextureCoordinates;
};

#define CustomVertexFormat (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)

It really does not take too long to learn, just spend some time at it!

Good luck!

-Rhone
TechleadEnilno, the Ultima 2 projectwww.dr-code.org/enilno
RhoneRanger
RhoneRanger
Start by following the tuts in the DirectX sdk docu.

All your hard work is not at a loss because the DrawPrimitive and DrawIndexedPrimitive functions are basically the same.

You just now have control over the vertex types and you have more control on how to manage them.

For example, DirectX7 had D3DLVERTEX as a type.

in DX8, you need to declare this.

struct CustomVertex
{
D3DXVECTOR3 Position;
DWORD Color;
D3DXVECTOR2 TextureCoordinates;
};

#define CustomVertexFormat (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)

It really does not take too long to learn, just spend some time at it!

Good luck!

-Rhone
TechleadEnilno, the Ultima 2 projectwww.dr-code.org/enilno
outRider
outRider
I think you misread, I know D3D has that, and that's exactly what I don't want.

Using that custom vertex I'll have one buffer (4 items) as follows:

xyz,c,st,xyz,c,st,xyz,c,st,xyz,c,st...

Where as my stuff is set up as multiple buffers:

xyz,xyz,xyz,xyz
c,c,c,c
st,st,st,st

OpenGL takes that happily... can it be done in D3D8?

------------
- outRider -

[edited by - outRider on February 15, 2003 1:37:55 AM]
RhoneRanger
RhoneRanger
okay, I guess I did misunderstand.

I will help, but I need some more info.

Are you saying this...
Your model has several different types of vertices (some are colored some are not, some are textured, some are not etc)

Or are you saying the vertices in your model have different colors etc.

I really dont understand 100% (yet) what you are saying....
TechleadEnilno, the Ultima 2 projectwww.dr-code.org/enilno
outRider
outRider
My vertices have a position, a color, and 1 texcoord, just like your FVF example. Instead of being in a single buffer like

struct CustomVertex
{
D3DXVECTOR3 Position;
DWORD Color;
D3DXVECTOR2 TextureCoordinates;
};

CustomVertex MyBuffer[10];

I have

D3DXVECTOR3 Vertices[10];
DWORD Colors[10];
D3DXVECTOR2 TexCoords[10];

------------
- outRider -
CrazedGenius
CrazedGenius
You should be able to do what you need with multiple streams. See the dolphinVS example in the SDK...

There are some limitations with this that escape me at this late hour. Basically, it'll do what you want, but you *might* have to jump through more hoops, depending on what exactly you're doing.


Author, "Real Time Rendering Tricks and Techniques in DirectX", "Focus on Curves and Surfaces"

[edited by - CrazedGenius on February 15, 2003 1:52:54 AM]
RhoneRanger
RhoneRanger
Okay, I think i am getting it (kinda) I just like to know for sure. I have been accused of being dense, but I just want to know all the details IN DETAIL before I give solid advice.

If your model has 10 vertices lets say, using the above code, I would write the vertex buffer like this


Device->CreateVertexBuffer(10*sizeof(CustomVertex), etc

CustomVertex* Verts;

Buffer->Lock(0,0,(BYTE**)&Verts,o);
Verts[0].Position=//
Verts[0].Color=//
Verts[0].TextureCoords=//

Verts[1]. get it?
TechleadEnilno, the Ultima 2 projectwww.dr-code.org/enilno
RhoneRanger
RhoneRanger
Okay, I get it (I think)

If you have VertexCoord[10]; VertexColor[10]; TextureCoordinate[10];

Here is what you need to do (after you lock the vertex buffer)
for(int i=0;i{
Vertex.Position=VertexCoord[i];
Vertex[i].Color=VertexColor[i];
Vertex[i].TextureCoord=TextureCoordinate[i];
}
Buffer->Unlock();
TechleadEnilno, the Ultima 2 projectwww.dr-code.org/enilno
outRider
outRider
It seems that to use multiple streams I also have to use a vertex shader. Using an FVF and the fixed function pipeline only works with stream 0.

Goddamn.

I would think that having your data seperate would be faster considering the SIMD nature of TNL cards.

------------
- outRider -
CrazedGenius
CrazedGenius
the docs say it''s slower, but I haven''t tested it either way...

creating a set of shaders that mimic the DX lights isn''t very hard. It might be worthwhile to reproduce the lights to gain the (architectural) advantage of multiple streams.

Author, "Real Time Rendering Tricks and Techniques in DirectX", "Focus on Curves and Surfaces"
Possibility
Possibility
The openGL method is very non-object oriented and to me doesnt make any sense, why would you want to have 3 seperate buffers for xyz, color and tex coordinates. That doesnt make any sense and that is why i cant stand openGL (among other reasons). If you want to switch to D3D your going to have to bite the bullet and just make the switch to 1 buffer with xyz,color,tex cordinates all in it. It makes alot more intuitive sense and you will grow to like it more then the openGL method.

Possibility
Donavon Keithley
Donavon Keithley
quote:
It seems that to use multiple streams I also have to use a vertex shader. Using an FVF and the fixed function pipeline only works with stream 0.


You can use multiple streams with FF processing. In D3D8 you call CreateVertexShader with a NULL token array which gives you the so-called "fixed function vertex shader". (Also check the MaxStreams cap.)

D3D9 allows multiple streams w/ FF directly without this special "shader" (presumably because vertex declarations have been decoupled from vertex shaders).

Multiple streams are not extremely expensive but they''re not free either, so the recommendation is to use them only with good reason.
CrazedGenius
CrazedGenius
quote:
Original post by Possibility
The openGL method is very non-object oriented and to me doesnt make any sense, why would you want to have 3 seperate buffers for xyz, color and tex coordinates. That doesnt make any sense


Lots of reasons. One of the nice things about the ARB is that many different people with many different viewpoints all decided that this was an interesting feature. Additional features are not a good reason to dislike an API, even if you personally don''t choose to use them.




Author, "Real Time Rendering Tricks and Techniques in DirectX", "Focus on Curves and Surfaces"
outRider
outRider
I think the best reason is that for TNL cards groups of vertices/vertex components can be transformed with one instruction. Just like you might stick 2/4/8 floats in a single register to operate on it using SSE2 or what have you, a TNL card does the same thing. Probably more convenient if the data is in contiguous memory, so you don''t have to fill the regs piecemeal, jumping around all over the place to do it.

Besides, you can interleave your data and still render it in GL, I was just hoping D3D gave me the same choice, since it''s what I''m used to.

Thanks for the help.

------------
- outRider -
Metron
Metron
Hi,

it is absolutely possible to keep your data as is. Say : Seperated xyz, txty, normals etc.

To do so, you have to create a streamdeclarator that declare the different data in seperate streams. Stream Declarators are explained within the DirectX documentation.

You then have to create a vertex shader that handles that data. Don''t worry. It''s absolutely possible to do this with the fixed function pipeline and you don''t have to "write" your own shader.

Simple take the stream declarator and hand it to the CreateVertexShader function of the d3d device. The function itself asks for a pointer to the vertex shader code. Simply put a NULL there. The driver will then create a vertex shader using the fixed function pipeline.

As for you data, you have to create different vertex buffers to fit your data in them. One for position, one for normals, one for diffuse color, etc.

There are some things to keep in the back of your head :

You have to declare the stream content within a given order. It''s documented within the DirectX documentation. I do not know under which chapter, though. Mustn''t be far from the streamdeclarator stuff

You also have to keep an eye to the cap bits concerning the number of simultaneous streams possible. Most cards support up to 16 different stream but you never know...

I hope this helps...

Kind regards,
Metron
----------------------------------------http://www.sidema.be----------------------------------------
outRider
outRider
Alright, I''ve gotten around to trying it this way.

I''ve created 2 vertex buffers and 1 index buffer. The VB are position and texcoord.


DWORD hStream0, Stream0Def[] = {D3DVSD_STREAM(0), D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), D3DVSD_END()};
DWORD hStream1, Stream1Def[] = {D3DVSD_STREAM(1), D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2), D3DVSD_END()};

assert(pD3DDevice->CreateVertexShader(Stream0Def, NULL, &hStream0, 0) == D3D_OK);
assert(pD3DDevice->CreateVertexShader(Stream1Def, NULL, &hStream1, 0) == D3D_OK);


Having done that, I''m unsure of what to do next. I set up 2 stream sources, VB1 and VB2, and then normally I''d call SetVertexShader() and pass it an FVF, but what do I do in this case, since I have 2 shaders? I''ve tried using LoadVertexShader() and loading them into slots 0 and 1, then using SelectVertexShade(), but that isn''t working...

------------
- outRider -
outRider
outRider
Nevermind, I figured it out. Just create a single definition with both streams in there and set that.

------------
- outRider -

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.