bobby
bobby

Reputation: 125

WebGL - multiple shapes but only one is rendered instead of the others

I have to draw multiple shapes in a simple WebGL program and there occurs a problem which seems unplausible for me. If I try to draw only a single shape, everything works fine.

In the "main" function I create the following instances and render them

_coneInstance = new Cone();
_coneInstance.initCone();

_cylinderInstance = new Cylinder();
_cylinderInstance.initCylinder();

_sphereInstance = new Sphere();
_sphereInstance.initSphere();

renderAll();

This leads to the problem, that all three objets looks like shapes enter image description here In renderAll() the render function of each object is called - these functions are shown below.

This looks like, that all vertices from the cone and the cylinder are overwritten by the sphere. Since each object drawn separately is correctly working, I will not post the vertex-building process.

function Cone()
{   
    ...
    this.vertexBuffer = 0;

    this.initCone = function()
    {        
        this.generateCone();
        this.initBuffers();
    }

    this.generateCone = function()
    {        
        ...
    }

    this.initBuffers = function()
    {        
        this.vertexBuffer = gl.createBuffer();
        this.bind();
        gl.bufferData(gl.ARRAY_BUFFER, flatten(this.triangleList), gl.STATIC_DRAW);

        gl.enableVertexAttribArray(vPosition);
        gl.vertexAttribPointer(vPosition, 4, gl.FLOAT, false, 0, 0);

        this.unbind();   
    }

    this.render = function()
    {    
        this.bind();
        gl.drawArrays(gl.TRIANGLE_FAN, 0, this.numTrianglesUpperPart);
        gl.drawArrays(gl.TRIANGLE_FAN, this.numTrianglesUpperPart, this.numTrianglesLowerPart);
        this.unbind();
    }   

    this.bind = function()
    {
        gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
        console.log(gl.isBuffer(this.vertexBuffer ));
    }

    this.unbind = function()
    {
        gl.bindBuffer(gl.ARRAY_BUFFER, null);
    }    
}


function Cylinder()
{   
    ...
    this.vertexBuffer = 0;

    this.initCylinder = function()
    {        
        this.generateCylinder();
        this.initCylinderBuffers();
    }

    this.generateCylinder = function()
    {        
        ... 
    }

    this.initCylinderBuffers = function()
    {        
        this.vertexBuffer = gl.createBuffer();
        this.bind();
        gl.bufferData(gl.ARRAY_BUFFER, flatten(this.cylinderVertexList), gl.STATIC_DRAW);

        gl.enableVertexAttribArray(vPosition);    
        gl.vertexAttribPointer(vPosition, 4, gl.FLOAT, false, 0, 0);

        this.unbind();     
    }

    this.render = function()
    {
        this.bind();        
        gl.drawArrays(gl.TRIANGLE_FAN, 0, this.cylinderNumTrianglesUpperPart);
        gl.drawArrays(gl.TRIANGLE_FAN, this.cylinderNumTrianglesUpperPart, this.cylinderNumTrianglesLowerPart);
        gl.drawArrays(gl.TRIANGLES, this.cylinderNumTrianglesUpperPart+this.cylinderNumTrianglesLowerPart, this.cylinderNumTrianglesMiddlePart);
        this.unbind();
    }    

    this.bind = function()
    {
        gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
        console.log(gl.isBuffer(this.vertexBuffer ));
    }

    this.unbind = function()
    {
        gl.bindBuffer(gl.ARRAY_BUFFER, null);
    }
}



function Sphere()
{   
    ...    
    this.vertexBuffer = 0;

    this.initSphere = function()
    { 
        this.generateSphere();
        this.initSphereBuffers();      
    }

    this.generateSphere = function()
    { 
        ...
    }

    this.initSphereBuffers = function()
    {        
        this.vertexBuffer = gl.createBuffer();       
        this.bind();
        gl.bufferData(gl.ARRAY_BUFFER, flatten(this.unindexedVertices), gl.STATIC_DRAW);

        gl.enableVertexAttribArray(vPosition);     
        gl.vertexAttribPointer(vPosition, 4, gl.FLOAT, false, 0, 0);

        this.unbind();
    }

    this.render = function()
    {
        this.bind();
        gl.drawArrays(gl.TRIANGLES, 0, this.numTriangles);
        this.unbind();
    }

    this.bind = function()
    {
        gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
        console.log(gl.isBuffer(this.vertexBuffer ));
    }

    this.unbind = function()
    {
        gl.bindBuffer(gl.ARRAY_BUFFER, null);
    }
}

Upvotes: 0

Views: 410

Answers (1)

LJᛃ
LJᛃ

Reputation: 8153

You have to update the attribute pointers to the buffer every time.

When binding a vertex attribute pointer you're setting a global pointer to the buffer currently bound. Having a bound buffer is a prerequisite for that, but it does not store any state in regards to vertex attribute pointers. So you have to either move the pointer setup into your render method or use the OES_vertex_array_object extension.

Your initBuffers functions need to be split

This part is "initing" a buffer and only needs to happen at init time

    this.vertexBuffer = gl.createBuffer();       
    this.bind();
    gl.bufferData(gl.ARRAY_BUFFER, flatten(this.unindexedVertices), gl.STATIC_DRAW);

This part needs to happen every time before you render

    this.bind();
    gl.enableVertexAttribArray(vPosition);     
    gl.vertexAttribPointer(vPosition, 4, gl.FLOAT, false, 0, 0);

Upvotes: 1

Related Questions