Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 6 of 6

Thread: glDrawElementsBaseVertex .. GL_TRIANGLE_STRIP .. height-field

  1. #1
    Intern Contributor
    Join Date
    Jul 2013
    Posts
    68

    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 1200*1200 vertices in a .. 1200*1200 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:
    Code :
    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:
    Code :
    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\n", indicesCount , counter ) ; // yes
        }

    Code :
    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:
    Code :
    ....
                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 );
    ....

  2. #2
    Intern Contributor
    Join Date
    Jul 2013
    Posts
    68
    Click image for larger version. 

Name:	strips.jpg 
Views:	61 
Size:	95.9 KB 
ID:	1197

    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.

  3. #3
    Member Regular Contributor
    Join Date
    Jan 2011
    Location
    Paris, France
    Posts
    250

    Quote Originally Posted by CarstenT View Post
    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 1200*1200 vertices in a .. 1200*1200 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:
    ]
    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 :
    Code :
    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)
    Last edited by The Little Body; 12-12-2013 at 04:06 PM.
    @+
    Yannoo

  4. #4
    Intern Contributor
    Join Date
    Jul 2013
    Posts
    68
    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_ELEMENTS*components - 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_ELEMENTS*components, 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.

  5. #5
    Intern Contributor
    Join Date
    Jul 2013
    Posts
    68
    I've extracted a 500*500 sub-tile of the 1200*1200 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? ..
    Click image for larger version. 

Name:	screen.jpg 
Views:	52 
Size:	94.5 KB 
ID:	1200
    The 'camera' 'looks at' the center of the tile (250,250).

  6. #6
    Intern Contributor
    Join Date
    Jul 2013
    Posts
    68
    Solved,

    glBufferData() wants an indices-bytesize and not an indices-count ...
    Click image for larger version. 

Name:	solved.jpg 
Views:	36 
Size:	98.0 KB 
ID:	1201
    Sometimes I wished that my mood wouldn't be that much dependent on these outputs. Anyway, the sun shines now ;o)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •