glDrawElementsBaseVertex .. GL_TRIANGLE_STRIP .. height-field

Hi all,

The drawing doesn’t get any easier than ‘doing’ a height-field.
I’ve got close, but still missing the last piece of the pussle.
The data is 12001200 vertices in a … 12001200 plain grid with height-values at the position.y.
My graphics-card has a limit of ~1 mill vertices (and do indices), so I’ve had to split the 1.4mill vertices. After trying different possibilities I’ve chosen to use glDrawElementsBaseVertex with GL_TRIANGLE_STRIP and to cut up the drawing into 4 calls.
To judge by the visual output it looks as if not all vertices in each call are drawn to the screen.
The calls splits as four broad bands (300*1200) vertices that conveniently are drawn as 300 GL_TRIANGLE_STRIPs. Approximately 1/4’th of the vertices seems to be drawn, but what DOES get drawn is ok and all positioned properly: I get a partly painted square with wide empty gaps in.
Doing only one call (1/4’th of 1.4 mill) does not affect the amount of vertices being drawn.

Kind of stupid question: but that leaves the problem at the VAO/VBO’s, doesn’t it?
Unless anyone can find the bug in the code:

Load and fill arrays:


const GLuint SRTM_SIZE = 1201;
Vertex3 Vertices[ SRTM_SIZE * SRTM_SIZE ] ;
static GLfloat vPosArray[ SRTM_SIZE * SRTM_SIZE ][4] ;
static GLfloat vNormArray[ SRTM_SIZE * SRTM_SIZE ][4] ;

    static GLint Load_1201_HGT(){
       //load file, 
        for (GLuint i = 0; i < SRTM_SIZE; ++i)
        {
            for (GLuint j = 0; j < SRTM_SIZE; ++j)
            {
                ..... read value "q"
                GLfloat p = (GLfloat) q/90 ;

                Vertex3 myVert;

                myVert.position.x = (GLfloat) j ;
                myVert.position.y = (GLfloat) p ;
                myVert.position.z = (GLfloat) i ;//

                Vertices[i * SRTM_SIZE + j] = myVert ;
                vPosArray[ i * SRTM_SIZE + j ][ 0 ] = (GLfloat) j ;
                vPosArray[ i * SRTM_SIZE + j ][ 1 ] =  p ;
                vPosArray[ i * SRTM_SIZE + j ][ 2 ] = (GLfloat) i ;
                vPosArray[ i * SRTM_SIZE + j ][ 3 ] = 1.0f ;
............
.......... calculate normals

            vNormArray[ i * SRTM_SIZE + j ][ 0 ] = norm.x ;// swap x and z ????
            vNormArray[ i * SRTM_SIZE + j ][ 1 ] = norm.y ;
            vNormArray[ i * SRTM_SIZE + j ][ 2 ] = norm.z ;
            vNormArray[ i * SRTM_SIZE + j ][ 3 ] = 1.0f ;


building indices:


const GLuint marker = 10000000 ; 
const GLuint indicesCount = 2*299*SRTM_SIZE + 299 ;
static  GLuint  Indices[indicesCount]  ; 

    void long4Indices(){
        GLuint counter = 0 ;
        GLuint lon = 0 ;
        GLuint lat = 0 ;
        //due to the 'symmetry' the lat = 1201 is skipped
        for( lat = 0; lat < 300 - 1 ; lat++ ) // lat iterates 299 times, but involves 2 lines (including +extra)
        {// two rows are traversed
            for( lon = 0; lon < SRTM_SIZE ; lon++ ) // lon iterates 1201 times
            {
                Indices[ counter ] = (GLuint)  lon + lat * SRTM_SIZE ;
                Indices[ counter + 1 ] = (GLuint)  lon + (lat + 1) * SRTM_SIZE ;
                counter += 2 ;
            }
            Indices[ counter ] = marker ;
            counter ++ ;
        }
        printf("is indices :  %i equal to counter : %i
", indicesCount , counter ) ; // yes
    }


GLuint vao; 
GLuint vertexBufferObject ;
GLuint indexBufferObject ;

	static void initProgram()
	{
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	//--- SRTM_SIZE * SRTM_SIZE vector of four floats (position or normals)
	size_t normalOffset = sizeof(float) * 4 * SRTM_SIZE * SRTM_SIZE;

	glGenBuffers(1, &vertexBufferObject);
	glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
	glBufferData(GL_ARRAY_BUFFER, normalOffset + normalOffset , NULL , GL_STATIC_DRAW);

	glBufferSubData( GL_ARRAY_BUFFER , 0 , normalOffset  , vPosArray ) ;
	glBufferSubData( GL_ARRAY_BUFFER , normalOffset , normalOffset , vNormArray ) ;

	glEnableVertexAttribArray(0); // positions
	glEnableVertexAttribArray(1); // normals
	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)0 ) ;
	glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)normalOffset ) ;

	glGenBuffers(1, &indexBufferObject);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);

	glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesCount , Indices , GL_STATIC_DRAW);
        glEnable( GL_PRIMITIVE_RESTART ) ; 
        glPrimitiveRestartIndex( marker ) ;
}//------------------------------------------------------------------------------

DISPLAY:


....
            glDrawElementsBaseVertex( GL_TRIANGLE_STRIP, indicesCount , GL_UNSIGNED_INT , (const GLvoid *)0 , 0 ); //
            glDrawElementsBaseVertex( GL_TRIANGLE_STRIP, indicesCount , GL_UNSIGNED_INT , (const GLvoid *)0 , 300*1201 );
            glDrawElementsBaseVertex( GL_TRIANGLE_STRIP, indicesCount , GL_UNSIGNED_INT , (const GLvoid *)0 , 2*300*1201 );
            glDrawElementsBaseVertex( GL_TRIANGLE_STRIP, indicesCount , GL_UNSIGNED_INT , (const GLvoid *)0 , 3*300*1201 );
....

[ATTACH=CONFIG]554[/ATTACH]

The image may inspire you to find my error …
Each draw Call outputs a strip.
Instead of stuffing positions and normals into the same vbo I’ve added a new so each has their own. It does not influence the output.

[QUOTE=CarstenT;1256754]Hi all,

The drawing doesn’t get any easier than ‘doing’ a height-field.
I’ve got close, but still missing the last piece of the pussle.
The data is 12001200 vertices in a … 12001200 plain grid with height-values at the position.y.
My graphics-card has a limit of ~1 mill vertices (and do indices), so I’ve had to split the 1.4mill vertices. After trying different possibilities I’ve chosen to use glDrawElementsBaseVertex with GL_TRIANGLE_STRIP and to cut up the drawing into 4 calls.
To judge by the visual output it looks as if not all vertices in each call are drawn to the screen.
The calls splits as four broad bands (300*1200) vertices that conveniently are drawn as 300 GL_TRIANGLE_STRIPs. Approximately 1/4’th of the vertices seems to be drawn, but what DOES get drawn is ok and all positioned properly: I get a partly painted square with wide empty gaps in.
Doing only one call (1/4’th of 1.4 mill) does not affect the amount of vertices being drawn.

Kind of stupid question: but that leaves the problem at the VAO/VBO’s, doesn’t it?
Unless anyone can find the bug in the code:
][/QUOTE]

Have you test with 16 bands instead that with only 4 ?

Because the memory needed for to store 1/4 of the 1.4 million (so 360 000 vertices) is perhaps too big for to be entirely stored into your on-board memory ?
(but I have make the computation and this make only something like 60 Mo of data => so, I don’t think that the problem can to be here)

And/or the glDrawElementsBaseVertex() call can only handle a limited number of elements ?
(about 65K if it can only deal with 16 bits unsigned integers indices on it’s internal circuitry for example => in your example yu use about 90K elements, so about 25K more indiices [and this make only something like 32K max indices with 16 bits signed internals indices, so only 1/4 of indices can really to be treated at each call])

What give glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &maxVertices) and glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &maxIndices) calls for examples ?

Or perhaps just use glDrawElementsBaseVertex( GL_QUAD_STRIP, …) instead of glDrawElementsBaseVertex( GL_TRIANGLE_STRIP, …) calls ?

Can you please post the entire code ?
(I have only tested the building indices code with Indices[ counter ] and Indices[ counter +1 ] commented and this give this :


is indices :  718497 equal to counter : 718497 

=> isn’t something like (360 000 / 4) * 2 indices = 180 000 indices that we have to handle for each call ?
(if we use quad strips with 2 new indices for each new quad)

Hi The Little Body,
Yes, I tried with 12 bands. The strips got thinner and still only ~1/4’th of the whole band is drawn.
I’m not using 16 bit integers for the indices.
GL_MAX_ELEMENTS_VERTICES and GL_MAX_ELEMENTS_INDICES are both slightly above 1 mill. I think that it’s here that the problem lies in the sense that these ‘specs’ may cover - MAX_ELEMENTScomponents - instead. That makes for only 1/4 of the full count when I use 4 component vectors (for position and normal). If the setup works with MAX_ELEMENTS_VERTICES = MAX_ELEMENTScomponents, then it’s still not enough to split the ‘heights’ in four tiles … I would have to split it all way down into 3*3 = nine tiles … that’s small, if I want equal size squares.
I read another post where generating triangle-strips in a geometry-shader had a practical max_input vertices for each strip far lower than ‘specs’. I looked forward to test the geometry-shader building TRIANGLE_STRIPs, but the poster expected much more than the 64 vertices he got per generated TRIANGLE_STRIP.
I’ve never used QUADS … I don’t think that it’s more efficient than GL_TRIANGLE_STRIP (in terms of low indices-count). If you glean the indices, you’ll notice that I use two rows of vertices to generate the 1200 row long (2400 total vertices) TRIANGLE_STRIP. I’ve glared a lot on it and found no errors.
Instead I’ve pondered weather there could be a shortcut by way of loading the heights in a texture, but I havn’t been there yet. It could give input components as low as two … u & v, but it still is no gain if the MAX is with respect to output-vertex-count (it’ll still have to be four component out) ;o/
I’ll post news when I’ve tried … something.
Great to get a response.

I’ve extracted a 500500 sub-tile of the 12001200 vertices. Neither GL_MAX_ELEMENTS_VERTICES nor GL_MAX_ELEMENTS_INDICES are exceeded. Only the first 1/4 of the vertices are drawn to screen. If I reduce the indices-count in glDrawElements to a few lines, it will be painted without errors. Making a 'glBeginQuery(GL_PRIMITIVES_GENERATED, myQuery ) I get a number that averages to the indices-count input. … (I’ll take a look at the GLsizei type), but aren’t a GL_PRIMITIVE something else than an index? …
[ATTACH=CONFIG]557[/ATTACH]
The ‘camera’ ‘looks at’ the center of the tile (250,250).

Solved,

glBufferData() wants an indices-bytesize and not an indices-count …
[ATTACH=CONFIG]558[/ATTACH]
Sometimes I wished that my mood wouldn’t be that much dependent on these outputs. Anyway, the sun shines now ;o)