Indexing Vertex and Texture Arrays

Started by
6 comments, last by jezham 15 years, 5 months ago
I'm currently working with OpenGL and VertexArrays/VBOs, but I have some difficulties finding a way to use vertices and indices efficiently. The problem is as follows: I'd like to be able to have vertex coordinates and texture coordinates and index them separately. Lets say that I have a vertex that 6 triangles share. Storing the data six times is inefficient, which is why you use indexed buffers instead - all fine. But what if I'd want to use different texture coordinates for the same vertex? I cannot store it as a single vertex array with strides to texture coordinates, because each vertex-position which should be reused could potentially have different texture coordinates. Do I have to duplicate vertex positions in case a vertex has two different sets of texture coordinate, or is there a smart way around this? The problem has come up with an .obj model loader which stores faces, i.e. triangles in this case, and each face consists of both a vertex position index and a texture coordinate index (and potentially also normals which would further create problems); they are at times indexed differently, and I cannot seem to find a way to use two different index buffers - one for each. What should I do? Any help is greatly appreciate, and feel free to ask me elaborate.
Advertisement
It's not possible to have seperate index buffers for verts and texcoords/colors/etc. I'll throw in a few suggestions for you to think about.

*Use per-vertex texturing (each vert is assigned a texture rather than each triangle).
*expanding on above, if some triangles require more textures than others then have seperate passes for each 'type' of triangle.
*Consider texture3d, I'm currently looking in to this to replace sub-tiles (see my post on antialiasing issues with sub-tiles). This might well be advisable anyway!

hth, your decision will depend on your exact circumstance really.
Quote:Original post by jezham
It's not possible to have seperate index buffers for verts and texcoords/colors/etc. I'll throw in a few suggestions for you to think about.


I didn't think so either, but it could be that there was a neat little solution.

Quote:Original post by jezham
*Use per-vertex texturing (each vert is assigned a texture rather than each triangle).
*expanding on above, if some triangles require more textures than others then have seperate passes for each 'type' of triangle.
*Consider texture3d, I'm currently looking in to this to replace sub-tiles (see my post on antialiasing issues with sub-tiles). This might well be advisable anyway!


A quick google search of per-vertex texturing did not give any results explaining this further. And in my head giving a vertex a texture - not a texture coordinate - does not make much sense. What's the idea?

Furthermore, I don't think that the problem is that some triangles requires more textures, but rather that each vertex could need more than one texture coordinate. Same goes for normal for corners of a cube.

The obj format gives faces with vertex/texture/normal indices - should I simply just use that info to generate and store non-indexed geometry as GL_TRIANGLES and then ignore the issue of wasting memory with duplicate positions?

There must be a better solution to this.

(if what was just proposed did provide a solution to the problem, then I guess I did not understand it fully)



Thanks for the answer so far.
Quote:Original post by dingojohn
A quick google search of per-vertex texturing did not give any results explaining this further. And in my head giving a vertex a texture - not a texture coordinate - does not make much sense. What's the idea?

For terrain it's a good and simple idea to define/edit on a vertex basis. You might use alpha to blend out the texture from one vert to the next, at the same time you would blend in the new texture. Over a triangle this would be just like supplying different colors to each vertex. I wouldn't attempt it without shader code though!
example snippet:
//frag shader...float3 color = (	tex2D( texturePack, uv0 ).xyz * weightsAndLight.r +			tex2D( texturePack, uv1 ).xyz * weightsAndLight.g +			tex2D( texturePack, uv2 ).xyz * weightsAndLight.b		) * weightsAndLight.w...

would be a simple linear blend of different textures at each of the 3 vertices of a triangle - that probably reads as well confusing compared to the code, sorry!

...it all gets a little deep (until you understand it then it's simple!) - and a simpler, though more restricted method, is to use texture3D: the 3rd coord (u, v, r) can be any float blending the output between 2 layers/textures.

You might also want to search for the more common "texture splatting" (I never really liked the idea but you might).

Btw, if you do look in to per-vertex-texturing then this is a good read (as is the whole journal!)
edit: you might want to go back a month from that link (to March 2008), for the first mention of terrain...it also discusses 'old' methods.

Quote:
Furthermore, I don't think that the problem is that some triangles requires more textures, but rather that each vertex could need more than one texture coordinate. Same goes for normal for corners of a cube.


Indeed, and you would pre-calculate this information based on whichever method you go with. Probably in to a VBO etc.

Quote:
The obj format gives faces with vertex/texture/normal indices - should I simply just use that info to generate and store non-indexed geometry as GL_TRIANGLES and then ignore the issue of wasting memory with duplicate positions?

There must be a better solution to this.


Yes I agree, which is why I optimize in any way possible (ex. 3 passes per scene, 1 for any triangles which share the same single texture, the other 2 for combination triangles - each called with it's own optimized shader).
I'm yet to find a method which would work with (quicker) indexed geometry...again I suggest you look in to texture3D if you don't fancy getting real deep in to shaders, the ones in the link above are based around next generation technology really - but the idea is workable now.

All of the methods should help you to find something which works for you, good luck! Hope I explained well enough, I'm kinda distracted here ;)

[Edited by - jezham on November 5, 2008 7:35:38 PM]
Quote:Original post by jezham
For terrain it's a good and simple idea to define/edit on a vertex basis. ...


Shader code is fine with me, it helps one understand it better. I think I understand where you are going, but I don't really think that multipass rendering with different vertices to blend textures is what is the problem. The information and link is invaluable though, especially since I am currently also working with terrain rendering - thanks! Problem being that rendering .obj files should not require doing a hassle like this, and I'd still like to save RAM on the graphics card.

Quote:
Indeed, and you would pre-calculate this information based on whichever method you go with. Probably in to a VBO etc.


Pre-calculate as in the proposed solution of indexing the things on the CPU before I save the info un-indexed in VRAM?

Quote:
I'm yet to find a method which would work with (quicker) indexed geometry...


I guess we are two then :\ Thanks so far.

Any other ideas?

Quote:Original post by dingojohn
Problem being that rendering .obj files should not require doing a hassle like this, and I'd still like to save RAM on the graphics card.
OBJ files are an editor friendly format, and were never intended to be an efficient runtime format.

Yes, you do need to 'weld' the obj arrays, into a single triangle buffer, duplicating vertices where necessary to preserve texture coordinates and normals. You should then re-index this buffer, to obtain an index triangle list which can be renderer efficiently.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Quote:Original post by swiftcoderYes, you do need to 'weld' the obj arrays, into a single triangle buffer, duplicating vertices where necessary to preserve texture coordinates and normals. You should then re-index this buffer, to obtain an index triangle list which can be renderer efficiently.


I'll just do that then. Had hoped for a better solution, but I guess there isn't any. Thanks.

Seems I didn't correctly identify your actual question. Sorry about that, but glad the info is useful to you! And you finally got your answers thanks to swiftcoder. As you're creating VBOs then you could of course search the file for weldable verts before building the buffer, might save you some time if the model's design isn't finished.

This topic is closed to new replies.

Advertisement