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 3 of 3

Thread: Graphics disappear under certain geometries.

  1. #1
    Newbie Newbie
    Join Date
    Jun 2014
    Posts
    2

    Graphics disappear under certain geometries.

    In the course of writing a little FEM project, a rather interesting bug was encountered. So this program simulates the displacement of a two dimensional body, fixed at certain points, under load. These bodies can be any simple polygon. Many bodies work fine; for instance a square and an L under loads:
    Click image for larger version. 

Name:	WorkingGraphics.jpg 
Views:	33 
Size:	3.5 KB 
ID:	1346

    Some bodies do not work fine. Upon changing the upper shape from a square to a backwards L, essentially mirroring in x the lower shape, it disappears!

    Click image for larger version. 

Name:	BrokenGraphics.jpg 
Views:	30 
Size:	3.1 KB 
ID:	1347

    Nothing has changed about it's position, rotation, or anything else I can tell. Just the specification of the outer hull.

    Weird, eh?

    Well, on to the code. Please feel free to point out where my code sucks, I'm rather new to OpenGL.

    First, a brief context. FEM breaks an object down into "elements" in order to calculate some result throughout that object. These elements, in this example, are triangles made of six nodes. Three nodes at their corners, and three at their midpoints. These can be seen in the above pictures. The nodes are represented as positions in 2d space, so two floats. The elements are represented as six indices to these nodes, so six unsigned integers, allowing some nodes to be reused.

    Now the code. Please feel free to tell me where my code sucks, as I'm rather new to OpenGL.

    This function sets up the OpenGL objects that are used in rendering. The physics pointer links to the object that is responsible for the FEM calculations.

    Code :
    void HullDraw::init() {
        PhysicsableMessage msg;
        msg.physicsable = &physics;
        getRoot()->handle(msg);
     
        unsigned int pPvbo, pCvbo;
        glGenBuffers(1, &pPvbo);
        glGenBuffers(1, &pCvbo);
        glGenVertexArrays(1, &pVao);
     
        vector<float> points, colours;
        for(unsigned int i = 0; i < physics->getNumNodes(); ++i) {
            points.push_back(physics->getNodePos()[X][i]);
            points.push_back(physics->getNodePos()[Y][i]);
     
            colours.push_back(1.f);
            colours.push_back(.3f);
            colours.push_back(.3f);
        }
     
        glBindBuffer(GL_ARRAY_BUFFER, pPvbo);
        glBufferData(GL_ARRAY_BUFFER,
                     points.size() * sizeof(float),
                     points.data(),
                     GL_STATIC_DRAW);
     
        glBindBuffer(GL_ARRAY_BUFFER, pCvbo);
        glBufferData(GL_ARRAY_BUFFER,
                     colours.size() * sizeof(float),
                     colours.data(),
                     GL_STATIC_DRAW);
     
        glBindVertexArray(pVao);
     
        glBindBuffer(GL_ARRAY_BUFFER, pPvbo);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
     
        glBindBuffer(GL_ARRAY_BUFFER, pCvbo);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
     
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
     
        //NOW DISPLACEMENTS
        glGenBuffers(1, &pPvbo);
        glGenBuffers(1, &pCvbo);
        glGenVertexArrays(1, &dVao);
     
        points.clear();
        colours.clear();
        for(unsigned int i = 0; i < physics->getNumNodes(); ++i) {
            points.push_back(physics->getNodeDis()[X][i]);
            points.push_back(physics->getNodeDis()[Y][i]);
     
            colours.push_back(.5f);
            colours.push_back(.5f);
            colours.push_back(1.f);
        }
     
        glBindBuffer(GL_ARRAY_BUFFER, pPvbo);
        glBufferData(GL_ARRAY_BUFFER,
                     points.size() * sizeof(float),
                     points.data(),
                     GL_STATIC_DRAW);
     
        glBindBuffer(GL_ARRAY_BUFFER, pCvbo);
        glBufferData(GL_ARRAY_BUFFER,
                     colours.size() * sizeof(float),
                     colours.data(),
                     GL_STATIC_DRAW);
     
        glBindVertexArray(dVao);
     
        glBindBuffer(GL_ARRAY_BUFFER, pPvbo);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
     
        glBindBuffer(GL_ARRAY_BUFFER, pCvbo);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
     
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
     
        glBindVertexArray(0);
     
        //And now indices....
        vector<unsigned int> indexV(physics->getNumElementNodes(), 0);
        nodes = physics->getNodesPerElement();
        elems = physics->getNumElements();
        unsigned int edges = nodes / 2;
        for(unsigned int i = 0; i < elems; ++i) {
            for(unsigned int n = 0; n < edges; ++n) {
                //Need n to go 0 3 1 4 2 5
                indexV[i * nodes + 2 * n + 0] = physics->getElemNod()[n + 0][i];
                indexV[i * nodes + 2 * n + 1] = physics->getElemNod()[n + 3][i];
            }
        }
     
        glGenBuffers(1, &indices);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                     indexV.size() * sizeof(unsigned int),
                     indexV.data(),
                     GL_STATIC_DRAW);
     
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        debugged = false;
    }

    Each time an object is drawn, it's position is queried from the physics object and glUniformMatrix4fv is used to set a model matrix in the used shader. This function is then called to draw all the original nodes, all the displaced nodes, and GL_LINE_LOOP of six displaced nodes each, using the element indices:

    Code :
    void HullDraw::run() {
        glBindVertexArray(pVao);
        glPointSize(2.0);
        glDrawArrays(GL_POINTS, 0, physics->getNumNodes());
        glBindVertexArray(0);
     
        glBindVertexArray(dVao);
        glPointSize(3.0);
        glDrawArrays(GL_POINTS, 0, physics->getNumNodes());
        glPointSize(1.0);
        glBindVertexArray(0);
     
        glBindVertexArray(dVao);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices);
        for(unsigned int i = 0; i < elems; ++i) {
            glDrawElements(GL_LINE_LOOP,
                           nodes,
                           GL_UNSIGNED_INT,
                           (void*)(i * nodes * sizeof(unsigned int)));
        }
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        glBindVertexArray(0);
     
        if(!debugged) {
            //Debug output generated here!
            debugged = true;
        }
    }

    In attempting to figure out what's happening, data was retreived using various calls to glGetVertexAttrib and glGetBufferSubData. Here's the output for a working an non-working example:

    Code :
    HullDraw :: Debug ------------------------ Working Example
    VertexArray pVao(3) bound
    GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING(0) = 8
    VertexArray 0 bound
    Buffer 8 bound to GL_ARRAY_BUFFER
        Contains [0, 10, 0, 0, 10, 0, 10, 5, 5, 5, 5, 10, 5, 0, 0, 5, 2.5, 0, 7.5, 2.5, 10, 2.5, 7.5, 5, 2.5, 7.5, 5, 7.5, 2.5, 10, 2.5, 2.5, 0, 2.5, 2.5, 5, 5, 2.5, 7.5, 0, 0, 7.5]
    Buffer 0 bound to GL_ARRAY_BUFFER
    VertexArray pVao(3) bound
    GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING(1) = 9
    VertexArray 0 bound
    Buffer 9 bound to GL_ARRAY_BUFFER
        Contains [1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3]
    Buffer 0 bound to GL_ARRAY_BUFFER
    VertexArray pVao(3) bound
    GL_VERTEX_ATTRIB_ARRAY_ENABLED(0) = 1
    GL_VERTEX_ATTRIB_ARRAY_ENABLED(1) = 1
    GL_VERTEX_ATTRIB_ARRAY_SIZE(0) = 2
    GL_VERTEX_ATTRIB_ARRAY_SIZE(1) = 3
    GL_VERTEX_ATTRIB_ARRAY_STRIDE(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_STRIDE(1) = 0
    GL_FLOAT = 5126
    GL_VERTEX_ATTRIB_ARRAY_TYPE(0) = 5126
    GL_VERTEX_ATTRIB_ARRAY_TYPE(1) = 5126
    GL_VERTEX_ATTRIB_ARRAY_NORMALIZED(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_NORMALIZED(1) = 0
    GL_VERTEX_ATTRIB_ARRAY_INTEGER(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_INTEGER(1) = 0
    GL_VERTEX_ATTRIB_ARRAY_DIVISOR(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_DIVISOR(1) = 0
    GL_CURRENT_VERTEX_ATTRIB(0) = [0, 0, 0, 1]
    GL_CURRENT_VERTEX_ATTRIB(1) = [1, 0, 0, 1]
    VertexArray dVao(4) bound
    GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING(0) = 10
    VertexArray 0 bound
    Buffer 10 bound to GL_ARRAY_BUFFER
        Contains [0, 10, -0.529294, 0.148426, 9.20434, -1.37926, 10.1515, 3.74684, 4.9973, 4.72948, 5, 10, 4.35036, -0.371619, 0, 5, 1.93815, -0.100438, 7.19151, 1.72836, 9.68394, 1.21394, 7.61157, 4.22781, 2.51778, 7.45039, 5.00136, 7.39146, 2.5, 10, 2.23168, 2.40813, -0.269872, 2.60885, 2.47385, 4.92229, 4.70552, 2.16422, 6.74973, -0.793537, 0, 7.5]
    Buffer 0 bound to GL_ARRAY_BUFFER
    VertexArray dVao(4) bound
    GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING(1) = 11
    VertexArray 0 bound
    Buffer 11 bound to GL_ARRAY_BUFFER
        Contains [0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1]
    Buffer 0 bound to GL_ARRAY_BUFFER
    VertexArray dVao(4) bound
    GL_VERTEX_ATTRIB_ARRAY_ENABLED(0) = 1
    GL_VERTEX_ATTRIB_ARRAY_ENABLED(1) = 1
    GL_VERTEX_ATTRIB_ARRAY_SIZE(0) = 2
    GL_VERTEX_ATTRIB_ARRAY_SIZE(1) = 3
    GL_VERTEX_ATTRIB_ARRAY_STRIDE(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_STRIDE(1) = 0
    GL_FLOAT = 5126
    GL_VERTEX_ATTRIB_ARRAY_TYPE(0) = 5126
    GL_VERTEX_ATTRIB_ARRAY_TYPE(1) = 5126
    GL_VERTEX_ATTRIB_ARRAY_NORMALIZED(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_NORMALIZED(1) = 0
    GL_VERTEX_ATTRIB_ARRAY_INTEGER(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_INTEGER(1) = 0
    GL_VERTEX_ATTRIB_ARRAY_DIVISOR(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_DIVISOR(1) = 0
    GL_CURRENT_VERTEX_ATTRIB(0) = [0, 0, 0, 1]
    GL_CURRENT_VERTEX_ATTRIB(1) = [1, 0, 0, 1]
    Indices: [3, 11, 4, 9, 2, 10, 5, 14, 0, 12, 4, 13, 1, 8, 6, 15, 7, 16, 6, 18, 4, 17, 7, 15, 2, 9, 4, 18, 6, 19, 4, 12, 0, 20, 7, 17]
     
     
     
    HullDraw :: Debug ------------------------ Broken Example
    VertexArray pVao(1) bound
    GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING(0) = 3
    VertexArray 0 bound
    Buffer 3 bound to GL_ARRAY_BUFFER
        Contains [0, 0, 10, 0, 10, 10, 5, 10, 5, 5, 0, 5, 10, 5, 5, 0, 10, 2.5, 7.5, 7.5, 10, 7.5, 7.5, 10, 2.5, 0, 2.5, 2.5, 0, 2.5, 5, 2.5, 7.5, 0, 7.5, 2.5, 2.5, 5, 5, 7.5, 7.5, 5]
    Buffer 0 bound to GL_ARRAY_BUFFER
    VertexArray pVao(1) bound
    GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING(1) = 4
    VertexArray 0 bound
    Buffer 4 bound to GL_ARRAY_BUFFER
        Contains [1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3]
    Buffer 0 bound to GL_ARRAY_BUFFER
    VertexArray pVao(1) bound
    GL_VERTEX_ATTRIB_ARRAY_ENABLED(0) = 1
    GL_VERTEX_ATTRIB_ARRAY_ENABLED(1) = 1
    GL_VERTEX_ATTRIB_ARRAY_SIZE(0) = 2
    GL_VERTEX_ATTRIB_ARRAY_SIZE(1) = 3
    GL_VERTEX_ATTRIB_ARRAY_STRIDE(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_STRIDE(1) = 0
    GL_FLOAT = 5126
    GL_VERTEX_ATTRIB_ARRAY_TYPE(0) = 5126
    GL_VERTEX_ATTRIB_ARRAY_TYPE(1) = 5126
    GL_VERTEX_ATTRIB_ARRAY_NORMALIZED(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_NORMALIZED(1) = 0
    GL_VERTEX_ATTRIB_ARRAY_INTEGER(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_INTEGER(1) = 0
    GL_VERTEX_ATTRIB_ARRAY_DIVISOR(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_DIVISOR(1) = 0
    GL_CURRENT_VERTEX_ATTRIB(0) = [0, 0, 0, 1]
    GL_CURRENT_VERTEX_ATTRIB(1) = [1, 0, 0, 1]
    VertexArray dVao(2) bound
    GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING(0) = 5
    VertexArray 0 bound
    Buffer 5 bound to GL_ARRAY_BUFFER
        Contains [0, 0, 9.90576, -0.379254, 10.7407, 9.3301, 5.70343, 10.0117, 5.1489, 4.94528, 0, 5, 10.2081, 4.55689, 5, 0, 10.0553, 2.10638, 7.90766, 7.22786, 10.4216, 6.95352, 8.20434, 9.71403, 2.5, 0, 2.52135, 2.50055, 0, 2.5, 5.04784, 2.4658, 7.43277, -0.199046, 7.552, 2.2869, 2.56458, 4.99254, 5.4052, 7.47837, 7.68379, 4.75436]
    Buffer 0 bound to GL_ARRAY_BUFFER
    VertexArray dVao(2) bound
    GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING(1) = 6
    VertexArray 0 bound
    Buffer 6 bound to GL_ARRAY_BUFFER
        Contains [0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1]
    Buffer 0 bound to GL_ARRAY_BUFFER
    VertexArray dVao(2) bound
    GL_VERTEX_ATTRIB_ARRAY_ENABLED(0) = 1
    GL_VERTEX_ATTRIB_ARRAY_ENABLED(1) = 1
    GL_VERTEX_ATTRIB_ARRAY_SIZE(0) = 2
    GL_VERTEX_ATTRIB_ARRAY_SIZE(1) = 3
    GL_VERTEX_ATTRIB_ARRAY_STRIDE(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_STRIDE(1) = 0
    GL_FLOAT = 5126
    GL_VERTEX_ATTRIB_ARRAY_TYPE(0) = 5126
    GL_VERTEX_ATTRIB_ARRAY_TYPE(1) = 5126
    GL_VERTEX_ATTRIB_ARRAY_NORMALIZED(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_NORMALIZED(1) = 0
    GL_VERTEX_ATTRIB_ARRAY_INTEGER(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_INTEGER(1) = 0
    GL_VERTEX_ATTRIB_ARRAY_DIVISOR(0) = 0
    GL_VERTEX_ATTRIB_ARRAY_DIVISOR(1) = 0
    GL_CURRENT_VERTEX_ATTRIB(0) = [0, 0, 0, 1]
    GL_CURRENT_VERTEX_ATTRIB(1) = [1, 0, 0, 1]
    Indices: [2, 11, 3, 9, 6, 10, 5, 14, 0, 12, 7, 13, 1, 17, 4, 15, 7, 16, 4, 18, 5, 13, 7, 15, 3, 19, 4, 20, 6, 9, 4, 17, 1, 8, 6, 20]

    The strange part is that all the data checks out, nothing seems to be wrong. The non-rendered object still has proper displacement calculcations. When we plot the points that occupy vertex array attribute 0 in dVao (the displaced positions) we get for the working example:
    Click image for larger version. 

Name:	WorkingPlot.jpg 
Views:	28 
Size:	6.9 KB 
ID:	1348

    ...and for the broken example:
    Click image for larger version. 

Name:	BrokenPlot.jpg 
Views:	25 
Size:	7.2 KB 
ID:	1349

    All the right data seems to be in the right places, but for some geometries, glDrawArrays and glDrawElements seem to work, and for some other geometries, seem to not work.

    ...wat?

  2. #2
    Junior Member Newbie
    Join Date
    Nov 2013
    Posts
    29
    see https://www.opengl.org/sdk/docs/man3...glCullFace.xml
    The default is to cull a polygon whose back is to the viewer.
    Add the disable, and those faces should reappear

  3. #3
    Newbie Newbie
    Join Date
    Jun 2014
    Posts
    2
    Nice thought. Had the same one myself when this all started.

    Doesn't work though.

    If you look at the rendering code, you see that it renders two VAOs as GL_POINTS, and then portions of the second VAO as GL_LINE_LOOPs. According to spec, glCullFace controls facets (triangles, quadrilaterals, polygons, and rectangles). Additionally, facet culling is initially disabled and, though you don't have all of my code, I haven't enabled it.

    Secondly, one can see in the debug output, the very last line for each example lists "Indices". These are the indices used, in consecutive groups of six, to render the line loops. If you find the points, in the vertex attribute 0 buffer, that these indices correspond to, you discover that the GL_LINE_LOOPs render counter-clockwise anyways.

    So yeah, GL_POINTS and GL_LINE_LOOP seem unaffected by culling, plus culling is off, plus all the shapes are counter-clockwise already.

    Thanks for the effort though.

Posting Permissions

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