Skip to main content
GameDev.net gamedev.net
🔒 Locked

Vertex Buffer and different Textures

Started by Synthesizer Dec 28, 2008 at 8:13 PM 8 replies 1.5k views
Original Post
Synthesizer
Synthesizer
Hi, I want to move my application to VERTEX BUFFER. Currenty I am using the following layout: A "Face", which has a Vertex[] and a Texture2D. A "Wall", which is a cube: 6 faces (so 6 textures). A "Room" which is made of 6 walls. So a Room has 36 different textures so u can see it from inside & from outside. I loop through all the faces, set the "xTexture" Effect Parameter corresponding to each Face and draw the Vertices of each Face. But this seems to be slow, so i thought of plotting evrth together once with the Vertex Buffer. Somehow I put aaall the vertices in an array & set the VertexBuffer. But the problem is that there may be different textures per surface & I CANNOT set one xTexture for all. I am not going to, I repeat: I AM NOT GOING TO use one big texture containing all the different images. So, is there any way I can solve this problem? Please, sorry me for my mood, but I've already wasted 2 months with Index Buffer (I am not using it now) & now again I face similar problems with Buffers & Textures. Thanks a lot
littlekid
littlekid
You are probably going to need to call draw for each different texture. However you would only need to set the VertexBuffer and IndexBuffer (if you use them) once.

SetVertexBuffer()
SetIndexBuffer()
SetTextureWall_1()
DrawWall_1()
SetTextureWall_2()
DrawWall_2()
...

In directx, the draw command can take in offset which allows you to draw from the proper location in the vertexbuffer. If you are using directx10, you can use texture arrays to set all the required textures and draw the room in a single draw call.

You should look into Mr Jack Hoxley's article on using a uber shader, material system if you are interested. In brief, in the shader it uses the SV_VertexID to identify which texture to use from the texture array.

Hope this helps
starman2049
starman2049
I am wondering why you are running slow - how big are your textures? How many lights do you have setup, and how many triangles per wall?
My Apps:Putt Nutz
Synthesizer
Synthesizer
Hi, thank u all for ur quick replies!

LittleKid,
I'm using XNA, and yes; I have my textures in arrays. But I'm not sure I can do what u say, since I'm on XNA. (I'll take a look anyway).

Starman2049,
It's not running slow actually, but I fly fluently during 2 seconds aprox & it stutters a bit. Then again 2 more seconds & a new stutter.

I'll tell u the details as soon as I get home, in a couple of hours, but I have one big cube: the container (the world), where u are inside (6 faces composed by several triangles per face so the texture doesn't stretch a lot); a little cube (6 faces: maybe 2 or 4 triangs per face) and a Room (made of 6 cubes, maybe 10 triangs per face or so).
I also have a X-Wing mesh (no textures) still in the air.
I think I'm using smth like 5 or 6 textures, no more.

I have only one light (I am increasing the x & z of it's position so it slowly moves giving a bit more of life to the scene ^^).

What I would also really like to ask u is what is the default measure... I mean, for example; how do you express 1 meter with a float number in XNA? I'm using simple values as 1f, 10f, etc.

I would also love to share some code with u, (the draw method for example).
How can I post it? I just paste the snippet here? Is it possible to post a screenshot of the render? how?

I'll add more precise info as soon as I come home in a couple of hours!
Super Thank u very much :)
Synthesizer
Synthesizer
Textures:
500x500 (732kb)
640x480 (900kb)
500x500 (143kb)
500x489 (288kb)

110 texture + normal triangles (if I counted correctly, which may not be very reliable as I'm an ape, so maybe more)
+
x-wing mesh (non-textured)

The biggest tiangle is (30f x 30f).


I have just tried to set the whole VertexBuffer, but I cannot as I should set it per face (each face a different texture). So i find no other way but setting it inside the loop...
Here:

        private void drawRooms()        {            for(int r = 0; r < rooms.Count; r++)            {                for(int w = 0; w < ((Room)rooms[r]).walls.Count; w++)                {                    for(int f = 0; f < 6; f++)                    {                        effect.Parameters["xTexture"].SetValue(((Face)((Cube)((Room)rooms[r]).walls[w]).faces[f]).texture);                        effect.Begin();                        foreach(EffectPass pass in effect.CurrentTechnique.Passes)                        {                            pass.Begin();                            device.VertexDeclaration = myVertexDeclaration;                            VertexBuffer myVertexBuffer = new VertexBuffer(device, ((Face)((Cube)((Room)rooms[r]).walls[w]).faces[f]).vertices.Length * VertexPositionNormalTexture.SizeInBytes, BufferUsage.WriteOnly);                            myVertexBuffer.SetData(((Face)((Cube)((Room)rooms[r]).walls[w]).faces[f]).vertices);                            device.Vertices[0].SetSource(myVertexBuffer, 0, VertexPositionNormalTexture.SizeInBytes);                                                        device.DrawPrimitives(PrimitiveType.TriangleList,0,((Face)((Cube)((Room)rooms[r]).walls[w]).faces[f]).vertices.Length / 3);                            //device.DrawUserPrimitives(PrimitiveType.TriangleList, ((Face)((Cube)((Room)rooms[r]).walls[w]).faces[f]).vertices, 0, ((Face)((Cube)((Room)rooms[r]).walls[w]).faces[f]).vertices.Length / 3);                                                        pass.End();                        }                        effect.End();                    }                }            }        }



I find SHAMEFUL things like you have to create a new VertexBuffer object that depends on things like the length of data you are gonna put in it. How am I supposed to know it?! Thus I have to create it after I already have all the data! So no benefit at all! It's like you go to a supermarket & need a different kind of bag for each & every product u buy, so they have to build the bags according to the things u previously bought... It's silly...
But the WORST thing is that you cannot send the textures together with the vertices to the buffer! So: a Vertice depends on a texture (because of the coords, because each texture may have different coords)... but u cannot set the texture the vertice is related to... Not in the vertice, not in the buffer! So how do I tell it that I want a wall with marble, wood & granite? Oh, I cannot? Not with a vertex buffer? SO...???!!!
God, we are in 2008 how can it be possible that we have to deal with this stuff? Am I the only one? I feel dissapointed. Same with Index Buffer: u cannot build a cube because of textures, OMG!!!

Boys, the problem is not with u, I'm just dissapointed about this things. But don't take it bad; hope u understand me! :)

Thanks a lot, if u can help me it would be marvelous!!
andur
andur
Don't be creating a new VertexBuffer every single draw call, that defeats the whole purpose of using them!

Allocate at the start of your program (or as soon as you can) a set of buffers big enough to contain all of your geometry and re-use them frame by frame. If you find that you need to re-size a vertex buffer later on, that's ok, as long as you aren't doing it constantly.

Those delays you are seeing every 2 seconds, sound suspiciously a lot like the garbage collector kicking in at those intervals. Try to reduce the number of objects that you are creating and destroying each frame to the absolute minimum possible (and re-use them if you can).
Synthesizer
Synthesizer
Wow, I think I'm getting the idea ^^

According to what u say, plus the fact that I've seen that each Model contains a VertexBuffer (or each Mesh, i don't remember) I come to 2 options:

1- To create a VertexBuffer per "Room" with the exact length & stuff (declared inside the Room class).

or

2- To create an only one VertexBuffer with a big (estimated) length in the beginning & Set the Data on each loop (I guess changing this parameter should make it possible: "BufferUsage.WriteOnly").

What do u think it's better? I guess the 1st is prettier, but I'm not sure about performance. (Also, if both options are none-sence just tell me :P)

Thank u very much guys, your help really helps :)


Matt Aufderheide
Matt Aufderheide
Alternatively, why not use D3DXMESHES? You can assign a seperate texture for each subset of a mesh, and then just render each subset seperately. Messing around with vetex buffers is not fun.

However, I still don't see why you can't try to pack more textures into single textures.. this is a basic method of 3D rendering; why are you against such things?
Synthesizer
Synthesizer
well, it's not that I'm against packing textures; I find it useful. But it's a mess to pack all the textures in one file. & I really don't find it fun to mess with texture coords & stuff.
Plus, for the moment, I just picked random pics from internet (just to see results), & each time i change the textures I should pack them in Photoshop, & measure the coords &...

About Meshes, I'm using XNA & I don't know how to create a Model, a ModelMesh, set the Bones & stuff. I know how to import it from an X file, though. I can hardly find any info about XNA.

This is who we are!
Evil Steve
Evil Steve
Quote:
Original post by Synthesizer
I find SHAMEFUL things like you have to create a new VertexBuffer object that depends on things like the length of data you are gonna put in it. How am I supposed to know it?! Thus I have to create it after I already have all the data! So no benefit at all! It's like you go to a supermarket & need a different kind of bag for each & every product u buy, so they have to build the bags according to the things u previously bought... It's silly...
But the WORST thing is that you cannot send the textures together with the vertices to the buffer! So: a Vertice depends on a texture (because of the coords, because each texture may have different coords)... but u cannot set the texture the vertice is related to... Not in the vertice, not in the buffer! So how do I tell it that I want a wall with marble, wood & granite? Oh, I cannot? Not with a vertex buffer? SO...???!!!
God, we are in 2008 how can it be possible that we have to deal with this stuff? Am I the only one? I feel dissapointed. Same with Index Buffer: u cannot build a cube because of textures, OMG!!!

Boys, the problem is not with u, I'm just dissapointed about this things. But don't take it bad; hope u understand me! :)

Thanks a lot, if u can help me it would be marvelous!!
A vertex is more than just a position, a vertex can contain texture coordinates, diffuse colour, specular colour, normals, and all sorts of other data. A vertex is only a duplicate of another if all of the data components are the same.
Similarly, an index is just a number referring to a vertex, it's index into the vertex buffer.

If you want to have a room of 4 walls, with each wall having a different texture, then you'll need to have duplicate vertices (Assuming the texture coordinates differ). A vertex is frequently around 32 bytes in size, on todays graphics cards, duplicating that data is nothing.

If you're really worried about it, you can use multiple vertex streams, and have the position in one stream and the texture coordinates in another - although this is often lower performance than just duplicating the vertices, since that's the normal way to handle it.

Quote:
It's like you go to a supermarket & need a different kind of bag for each & every product u buy, so they have to build the bags according to the things u previously bought... It's silly...
No, you'd get a bag which is big enough for what you think you'll buy. If it's too much, you get another bag and split the contents across two bags, or get a new, larger bag and put the entire contents in the larger bag.

Topic Locked

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

Sign in to reply to this topic.