PDA

View Full Version : giving per-face-color in vertex array mode



g-hennux
01-30-2008, 04:01 PM
Hi!

I'm writing a geometry viewer in OpenGL, or, more precisely, I'm replacing a perfectly working software renderer by one using OpenGL (with Java and JOGL, by the way). The purpose of this viewer is to be able to examine the properties of that geometry, how faces are connected etc., i.e. we want flat shading (to see the borders between faces) and especially, it might happen that adjacent faces have completely different colors.

In the past, I discovered that immediate mode, where I could say

glColor, glVertex, glVertex, glVertex
glColor, glVertex, glVertex, glVertex
...
was not fast enough, i.e. the overhead caused by JOGL and all the function calls and the massive duplication of vertices made this almost as slow as our software renderer. Now I'm using vertex arrays (which is a lot faster), that is, I create an array of 3*n doubles

{v1_x, v1_y, v1_z, ..., vn_x, vn_y,vn_z}
containing the coordinates of the n vertices and pass this with glVertexPointer. Then I have a 3*m integer array that stores the connectivity, i.e. the indices of the vertices that form one of the m triangles

{t1_1, t1_2, t1_3, t2_1, t2_2, t2_3, ..., tm_1, tm_2, tm_3}
which are passed with glDrawElements.

Normally you would now create another array specifying the colors for all vertices

{v1_r, v1_g, v1_b, ..., vn_r, vn_g, vn_b}
and passing this with glColorPointer. Now the problem is that I want my faces to have one given color; one face shall become red, another one blue and a third green. From what I've seen so far, OpenGL only allows to give the color per vertex, which is not what I want. Using immediate mode, the desired effect could be achieved because one vertex was duplicated one time for every adjacent triangle. This is not the case in vertex-array-mode, I cannot say "dear vertex, please, for this triangle, use red, but for the other one, use blue".

With flat shading, only the last vertex of a triangle determines its color, so it might be possible to achieve the per-face-coloring by finding an injective mapping from faces to vertices, so that I know for every face what vertex needs to be given the desired color. However, there are usually much more faces than triangles; thus, such a mapping cannot be found for most surfaces.

Now my question: What can I do to have the colors set per element without duplicating vertices in my array (consumes too much memory), as I do in immediate mode? The perfect case would be to construct an array

{v1_r, v1_g, v1_b, ..., vm_r, vm_g, vm_b}
which stores the RGB colors per-face instead of per-element.

I wonder if this is really such a rare thing one wants to do and am looking forward to receiving any hints you have for me!

Bye
Tobias

dorbie
01-30-2008, 04:48 PM
glShadeModel(GL_FLAT);

This will use the color last issued when the tri completes to shade the triangle (or lighting results) the only issue is it's truly flat interpolation so if you want to adjust color but still have variations in lighting it won't work, but if you want flatshading it will be just fine.

The benefit here is you can mesh corectly for a contiguous topology then simply ensure teh color on the vert for each triangle is correct for that tri.

If you index of course that invoking vertex and color will be shared and you need a new vertex, color and index for each triangle. So perhaps you just want drawarrays instead of drawelements because the indexing implies that all vertex data is common, and the would not give unique colors per triangle.

i.e. if you truly have unique colors then index information will not reuse and benefit from cache coherency so you might as well abandon it (emphasis on the IF). You can still have tristrips though and reduced calling overhead. Degenerates are also your friend (indices can cull them early too so if you have a lot revisit the indexing question).

tamlin
02-02-2008, 03:51 PM
I create an array of 3*n doubles
I'd prefer float - both for speed and memory consumption.