Vertex arrays and ... texture arrays

glVertexPointer et al are all very useful if you are trying to avoid large numbers of api calls. However, glDrawElements is only useful it seems when you have the unlikely situation that your scene is to be rendered using a single texture.

Why is there no glTextureObjectPointer or similar - containing the texture object names that you want to use for your primitives drawn with glDrawElements?

Or am I just going to have to call glDrawElements over and over, doing a glBindTexture each time?

Dammit.

Cas

Hi!
There is no function like gltexobjpoiner available.And it wouldn´t make too much sense,´cause in most cases not all textures fit into your video-cards-memory which means that it is very slow to change the texture very often.In nearly every 3dApp nowadays,the scene is sort by textures(after vis-determination) and then you can render all primitives with the same texture in one glDrawElements-Call.
HTH,XBTC!

[This message has been edited by XBCT (edited 06-21-2000).]

I thought I might end up having to sort by texture myself. I suppose this will cut down on glDrawElements and bind calls. However this begs the question as to whether I can sort it fast enough to be worth the overhead a few thousand API calls will impose. Benchmark time!

The scene I’m drawing is unfortunately exactly the unusual case which no-one else is doing - with up to 256 almost completely random textures drawn on 2000 placed polys in no particlar order.

Still… a useful idea for an extension, eh?

First off cix>foo, you can use glDrawElements when multitexturing. To minimize this api call, you just need to sort the polygons by their texture(s) if the polygons are opaque.

Heh heh - two minute lag! I’m already on the case, ta.

Cas

I have this “problem” too.
Is it possible to use glDrawElements to draw quad strips where each quad has its own texture coordinates ?
I have a big texture divided in tiles and I’d like to render the strip in one call !

This isn’t exactly the problem I have; what you want to do it easy - unless you want completely different texture coordinates on each point.

I have a feeling you’re writing a tile based map renderer or something…? You’ve got perhaps one big texture with all the tiles in it and you want to use quad strips to render a map? (I’m guessing but this is similar to what I’m doing)

You basically can’t use quad strips, you’ll have to use plain quads. Wastes a bit of vertex processing unfortunately.

(I might be wrong in this - perhaps you specify more texture coordinates than vertex coordinates for quad strips)

[This message has been edited by cix>foo (edited 06-22-2000).]

If your textures don´t change at runtime,you only have to sort them one time by texture.
Take an array in which your face-structs are stored,and sort it in ascending(or descending order) then you render your the triangles from the 0 element in the aray to the last and change the textures.You have to change so textures only as often as there are different ones if you do so.

HTH,XBTC!

You make me think of 1 thing : in my 3D engine, i will use BSPs to get visibles polygons. That means that i will draw polygons that have very differents textures and will cut down speed.
Anyone has a clue about it ? Could it be a good idea to sort the polygons by texture while reading the tree ?

Yes, that is probably one of the best ways to do it. As you walk the BSP simply chain the polygons to a texture object (and other polys using the same texture to the previous polygon chained.) If a polygon is transparent then you should chain it to a special chain of transparent polygons rather than to a texture specific chain. Probably be a good idea to chain the texture objects too as they are first encountered in the walk. After you have finished walking the tree, just walk the chain of texture objects and for each texture object, draw its chain of polygons. After all texture specific chains have been drawn, draw the transparent chain with depth writes disabled and depth testing enabled.
Remember to break the chains as they are drawn to prepare the polygons and textures for the next frame.

[This message has been edited by DFrey (edited 06-24-2000).]

Don´t really understand what dfrey sais but it sounds unnecesary difficult.Just give your poly-struct a Bool,which is flagged if the poly is visible.At the start of your app you sort your array of polys by texture(in or ascending(descending) order with qsort).

Then at runtime,you traverse your tree and flag all visible Faces as Visible.Now you go throug your array and render the visible polys from 0 to num_poly and voila you have as few texture-changes as possible.

HTH,XBTC!

[This message has been edited by XBCT (edited 06-24-2000).]

My way is similar to what you suggest but it eliminates the need to go back through the array to check for visible polygons. Instead each texture used in the scene points to a polygon in the scene that uses that particular texture. That polygon in turn points to another polygon that uses that same texture and so on for each polygon that uses that texture. The texture also points to the last polygon in its chain so when another polygon needs to be added I can immediately do so. I learned this trick from the glQuake source code.

[This message has been edited by DFrey (edited 06-24-2000).]

Hmm…I think I understand now.Seems to be faster than my idea.But even with the chained polys(same as a linked lists if I understand it),you´ll have to make a new array of indices for every chain which can then be thrown into glDrawElements.I think this is the real (speed-)problem.Do you make a indices list fo every chain ahead of time?

Greets,XBTC!

You are correct, but I don’t make the new indices ahead of time, that is something to think about , instead I make the indices list for each chain just by walking the chain and copying each polygons indices. Then I call glDrawElements. So it is still only one api call per chain to draw that chain, not counting any extra stuff that might be necessary (blending, stenciling, extra passes, etc.) for those polygons for special effects. I’m very happy with the FPS I’m getting too.

[This message has been edited by DFrey (edited 06-24-2000).]

Dfrey, I’m sorry to bother you. I’m a newbie and I just figured out how to do texture mapping and lighting =).
I do understand vertex arrays and such. I have a question for you. The indeces you say you fill in as you walk down the chain, to what are they referring. To a vertex array containing ALL vertices in the scene, or a vertex array only containing the arrays that are visible?

It may be a stupid question, I don’t know =)

I have a nother question too! You say you sort transparent polys in a separate chain, I understand this. But do you depth sort those polygons (in the chain) as well? Is it necessary to depth sort blended polygons?

Oh and a third question! =) You must have a data-structure describin each polygon right? Am I right in assuming that it contains an array with three elements to hold the indeces for that poly? And an int to keep track of which texture it uses? And texture coords? Or do you have a texcoord array for that?

Man, I’m thinking up my own engine as I go along here =) hehe…

To answer the first question, I have one array that contains all vertices in the world, not just in the scene. I also have another array that contains all indices for each face in the world. The face structure simply points to where its list of indices begin within the world indices list, and how many are in its list.

For the second question, transparent polygons must be depth sorted to be drawn correctly you are right (without using destination alpha). But when you walk the BSP, the transparent faces fall out already in proper order. If I need to also draw temporary transparent polygons, those have to be inserted into the chain using a fast insertion sort.

For the third question, as you note in my answer to the first question, I do have a structure per face (polygon). Instead of a int to index an array of texture objects, the face structure actually contains a pointer to its texture object. The face structure also points to the list of texture coordinates that are to be used with the vertices if the texture coordinates are not otherwise generated for special effects such as environment mapping, turbulance, noise, decals, affine transforms, and so forth. So I actually build an array of indices and an array of texture coordinates for every frame.
And I’m planning on also building an array of vertices so that I can arbitrarily deform the faces in real time.

[This message has been edited by DFrey (edited 06-24-2000).]

Thanks for the answer!

The face structure also points to the list of texture coordinates that are to be used with the vertices

Does this follow the same principle as with the indeces-list. Ie, do you have an array containing the texture coordinates of all the faces’ vertices in the world from which you gather you texcoords?
If so, do you create duplicates of the same vertex if you have to faces with a point in the same space but with different texture coordinates?

Let me get this straight. As you wander throught the BSP-tree, you generate an array of indices (specifying where to find the vertexes in the “global” vertex array) for each chain so that you may later render each “texture chain” by calling glDrawElements() and specifying the indeces of that chain.

The rendering is then a matter of taking each chain, changing the texture in accordance with it and calling glDrawElements() with the indices for that chain, before proceding to the next chain.

Have I understood that correctly?
You say you “build an array of texture coordinates” each frame, but then you cant use glDrawElements() can you? Because glDrawElements() will look in the texcoords array using the indeces you use for the vertex array no?
How do you specify the texcoords for each vertex? Do you call a glBegin() and loop through the “texture chain” setting the vertices and texture coordinates as you read them from the chain or what?

I’m don’t have the knowledge to build any engine yet, but I’m trying to gather any information I can in preparation for next years Computer Games Festival (a swedish thing) =).

[This message has been edited by Caesar (edited 06-24-2000).]


Does this follow the same principle as with the indeces-list. Ie, do you have an array containing the texture coordinates of all the faces’ vertices in the world from which you gather you texcoords?

Yes, for those polygons whose texture coordinates are constant, I just copy them from the list. For other polygons I copy and then transform them. And for still other polygons, I simply create the texture coordinates.


If so, do you create duplicates of the same vertex if you have to faces with a point in the same space but with different texture coordinates?

Yes. I do this because I’m using vertex arrays. You can’t use one index to point to two different texture entries in the texture array.


Let me get this straight. As you wander throught the BSP-tree, you generate an array of indices (specifying where to find the vertexes in the “global” vertex array) for each chain so that you may later render each “texture chain” by calling glDrawElements() and specifying the indeces of that chain.

Not exactly. What I create when walking the BSP is a set of texture sorted polygon chains and one chain of depth sorted transparent polygons.
Then for each chain, one at a time, I walk it, filling the indices array, the texture array, and the color array. I then call glDrawElements. And then repeat with the next chain.

[b]
The rendering is then a matter of taking each chain, changing the texture in accordance with it and calling glDrawElements() with the indices for that chain, before proceding to the next chain.

Have I understood that correctly?
[/b]

Yes, essentially. There are the other little details I just mentioned above.


You say you “build an array of texture coordinates” each frame, but then you cant use glDrawElements() can you?

Oh yes, why not? By build I simply mean fill.

[This message has been edited by DFrey (edited 06-24-2000).]

Thanks again for your reply!

Not exactly. What I create when walking the BSP is a set of texture sorted polygon chains and one chain of depth sorted transparent polygons.
Then for each chain, one at a time, I walk it, filling the indices array, the texture array, and the color array. I then call glDrawElements. And then repeat with the next chain.

Isn’t this a waste of time? Couldn’t you fill in the indeces-array WHILE you’re ading faces. You already handling the face, why not just fill in the indices array as well? Save you the trouble of walking through the chains won’t it?

Oh yes, why not? By build I simply mean fill.

I don’t understand this. Doesn’t glDrawElements() retrieve the texcoords in the array specified with glTexCoordsPointer() by using the indices you specify?
But the indices are referring to a huge vertex array, while you say you build the texture coords array just for that chain. So how does glDrawElements() know that texcoords[5] (an element in the relativly small tex coords array of that chain) goes with vertex[1004] (the huge vertex array) if that was the case?
Have I missed something?
I thought you would have to have a huge texture coordinates array for your entire world that corresponds with the vertex array.
But if that was the case i don’t understand what you mean by “filling” a texture array, it would already be filled and would be adressed by the same indices as the vertex array.
Have I gotten something terribly wrong here?

I’m sorry to take up your time with, for you, stupid questions. But I have another one.
How do you decide which texture chain to put a certain face in? Do you traverse the chain of texture chains to see if the texture-pointer matches one of them?
If so, there should be a faster way of doing it.
You could have an array of texture chains, with as many elements as there are textures in your world. You would also have an array with pointers to your textures. The face-struct would not contain the pointer to your texture but the index of its texture in the texture-pointer-array.
Now. Assigning a face to the texture-chain is simle: texture_chain_array[face.texture_index].assign(&face); or something like that.
The CTextureChain::assign()-function would then check to see if it’s LastFace-pointer is NULL (that is, if it doesn’t have any faces yet) and if it is, it will add the new face and then add a pointer to itself to the texture-chains linked list.
Did that make sense?
You should in other words have a linked list of “active” texture chains, and the texture chains will add themselves to this list if they receive a face.
That way, adding a face to the correct texture chain is the simple matter of assigning a pointer to an element in an array. You don’t have to compare texture-pointers at all.
It’s quite possible that I missed the obvious way of assigning faces to your texture chains. If so I apologize for making you read even more clueless rants.

Again, thanks for taking the time to answer my questions.


I don’t understand this. Doesn’t glDrawElements() retrieve the texcoords in the array specified with glTexCoordsPointer() by using the indices you specify?

Yes.


But the indices are referring to a huge vertex array, while you say you build the texture coords array just for that chain. So how does glDrawElements() know that texcoords[5] (an element in the relativly small tex coords array of that chain) goes with vertex[1004] (the huge vertex array) if that was the case?
Have I missed something?

No you didn’t miss anything. I did !
I forgot that I do also fill a vertex array too, and the indices are not copied but created. The world indices are only used to get the vertices out of the world vertex array. Sorry for the confusion, I had to take a second look at my code to see where my thoughts went astray.


How do you decide which texture chain to put a certain face in?

Each face contains a pointer to the texture object which describes the visual and physical properties of the face. The texture object also points to the root and terminus of its polygon chain.


You should … have a linked list of “active” texture chains, and the texture chains will add themselves to this list if they receive a face.

This is exactly what I do, but only if the texture object is opaque.


Again, thanks for taking the time to answer my questions.

Hey? What’s the forum for otherwise?

[This message has been edited by DFrey (edited 06-24-2000).]