WebGL - 多种形状但只呈现一个而不是其他

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

我必须在一个简单的 WebGL 程序中绘制多个形状,并且出现了一个对我来说似乎难以置信的问题。如果我尝试只绘制一个形状,一切正常。

在 "main" 函数中,我创建了以下实例并渲染它们

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

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

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

renderAll();

这导致了问题,所有三个对象看起来都像形状 在 renderAll() 中调用每个对象的渲染函数 - 这些函数如下所示。

看起来,圆锥体和圆柱体的所有顶点都被球体覆盖了。 由于单独绘制的每个对象都可以正常工作,因此我不会 post 顶点构建过程。

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);
    }
}

您每次都必须更新指向缓冲区的属性指针。

绑定顶点属性指针时,您正在设置一个指向当前绑定缓冲区的全局指针。有一个绑定缓冲区是先决条件,但它不存储关于顶点属性指针的任何状态。因此,您必须将指针设置移动到渲染方法中或使用 OES_vertex_array_object extension.

您的 initBuffers 函数需要拆分

这部分是"initing"一个缓冲区,只需要在初始化时发生

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

这部分需要在每次渲染之前发生

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