WebGl 将多个对象添加到一个 canvas

WebGl adding multiple objects to one canvas

这是我在 WebGL 中的第一个实验:我正在尝试将立方体、八面体和四面体添加到单个 canvas。我分别对每个形状进行了编程并对其进行了测试:它们在各自的 canvases 中工作。当我尝试将它们加在一起时,事情就出错了。目前我只看到八面体在旋转(不,它没有遮挡其他形状,我已经检查过了)。当我注释掉八面体时,我看到立方体和四面体在旋转,但它们的颜色缓冲区已经混合在一起并且不是我想要的(当我尝试分离它们的颜色缓冲区时,没有任何东西呈现到屏幕上)。我意识到我的编码方式存在不一致,但目前的配置是我可以同时显示这两个对象的唯一方式。现在最近添加的八面体使前两个消失了。

我感觉这个问题与顶点和颜色缓冲区有关,但我没有足够的经验和背景来知道要修改什么。我是否为其中的每一个实例化一个颜色缓冲区?那是有道理的。我试过了,但是前两个形状效果不佳,因此混合了颜色缓冲区。

如果有人能就此提出建议/帮助我,我将不胜感激。已经花了无数个小时试图解决这个问题。

var canvas;
var gl;

var NumVertices  = 36;

var points = [];
var colors = [];

var pointsT = [];
var colorsT = [];

var pointsO = [];
var colorsO = [];

var xAxis = 0;
var yAxis = 1;
var zAxis = 2;

var axis = 0;
var theta = [ 0, 0, 0 ];

var thetaLoc;

window.onload = function init()
{
    canvas = document.getElementById( "gl-canvas" );

    gl = WebGLUtils.setupWebGL( canvas );
    if ( !gl ) { alert( "WebGL is not available" ); }


    // --------------- Cube --------------------------

    colorCube();

    // --------------- Tetrahedron -------------------

    colorTetra();

    // --------------- Octohedron --------------------

    colorOcto();


    gl.viewport( 0, 0, canvas.width, canvas.height );
    gl.clearColor( 0.1, 0.1, 0.1, 1.0 );

    gl.enable(gl.DEPTH_TEST);


    // --------------- Load shaders and initialize attribute buffers

    // --------------- Cube --------------------------
    var program = initShaders( gl, "vertex-shader", "fragment-shader" );
    gl.useProgram( program );

    var cBuffer = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, cBuffer );
    gl.bufferData( gl.ARRAY_BUFFER, flatten(colors), gl.STATIC_DRAW );

    var vColor = gl.getAttribLocation( program, "vColor" );
    gl.vertexAttribPointer( vColor, 4, gl.FLOAT, false, 0, 0 );
    gl.enableVertexAttribArray( vColor );

    var vBuffer = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer );
    gl.bufferData( gl.ARRAY_BUFFER, flatten(points), gl.STATIC_DRAW );

    var vPosition = gl.getAttribLocation( program, "vPosition" );
    gl.vertexAttribPointer( vPosition, 3, gl.FLOAT, false, 0, 0 );
    gl.enableVertexAttribArray( vPosition );

    thetaLoc = gl.getUniformLocation(program, "theta"); 


    // --------------- Tetrahedron -------------------

    var tcBuffer = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, tcBuffer );
    gl.bufferData( gl.ARRAY_BUFFER, flatten(colors), gl.STATIC_DRAW );

    var tvColor = gl.getAttribLocation( program, "vColor" );
    gl.vertexAttribPointer( tvColor, 3, gl.FLOAT, false, 0, 0 );
    gl.enableVertexAttribArray( tvColor );

    var tvBuffer = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, tvBuffer);
    gl.bufferData( gl.ARRAY_BUFFER, flatten(points), gl.STATIC_DRAW );

    var tvPosition = gl.getAttribLocation( program, "vPosition" );
    gl.vertexAttribPointer( tvPosition, 3, gl.FLOAT, false, 0, 0 );
    gl.enableVertexAttribArray( tvPosition );


    // --------------- Octohedron --------------------      

    var ocBuffer = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, ocBuffer );
    gl.bufferData( gl.ARRAY_BUFFER, flatten(colorsO), gl.STATIC_DRAW );

    var ovColor = gl.getAttribLocation( program, "vColor" );
    gl.vertexAttribPointer( ovColor, 3, gl.FLOAT, false, 0, 0 );
    gl.enableVertexAttribArray( ovColor );

    var ovBuffer = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, ovBuffer );
    gl.bufferData( gl.ARRAY_BUFFER, flatten(pointsO), gl.STATIC_DRAW );

    var ovPosition = gl.getAttribLocation( program, "vPosition" );
    gl.vertexAttribPointer( ovPosition, 3, gl.FLOAT, false, 0, 0 );
    gl.enableVertexAttribArray( ovPosition );

    render();
}

function render()
{
    gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    theta[axis] += 2.0;
    gl.uniform3fv(thetaLoc, theta);

    // Render cube
    gl.drawArrays( gl.TRIANGLES, 0, NumVertices );

    // Render tetrahedron
    gl.drawArrays( gl.TRIANGLES, 0, points.length );

    // Render sphere
    gl.drawArrays( gl.TRIANGLES, 0, pointsO.length );
    requestAnimFrame( render );
}


// DEFINE CUBE

function colorCube()
{
    quad( 1, 0, 3, 2 );
    quad( 2, 3, 7, 6 );
    quad( 3, 0, 4, 7 );
    quad( 6, 5, 1, 2 );
    quad( 4, 5, 6, 7 );
    quad( 5, 4, 0, 1 );
}

function quad(a, b, c, d) 
{
    var vertices = [
        vec3( -0.25, -0.25,  0.25 ),
        vec3( -0.25,  0.25,  0.25 ),
        vec3(  0.25,  0.25,  0.25 ),
        vec3(  0.25, -0.25,  0.25 ),
        vec3( -0.25, -0.25, -0.25 ),
        vec3( -0.25,  0.25, -0.25 ),
        vec3(  0.25,  0.25, -0.25 ),
        vec3(  0.25, -0.25, -0.25 )
    ];

    var vertexColors = [
        [ 0.9, 0.9, 0.2, 1.0 ],  // oarnge
        [ 1.0, 0.0, 0.0, 1.0 ],  // red
        [ 1.0, 1.0, 0.0, 1.0 ],  // yellow
        [ 0.0, 1.0, 0.0, 1.0 ],  // green
        [ 0.0, 0.0, 1.0, 1.0 ],  // blue
        [ 1.0, 0.0, 1.0, 1.0 ],  // magenta
        [ 1.0, 1.0, 1.0, 1.0 ],  // white
        [ 0.0, 1.0, 1.0, 1.0 ]   // cyan
    ];

    // Partion the quad into two triangles in order for
    // WebGL to be able to render it.      
    // vertex color assigned by the index of the vertex

    var indices = [ a, b, c, a, c, d ];

    for ( var i = 0; i < indices.length; ++i ) {
        points.push( vertices[indices[i]] );
        colors.push( vertexColors[indices[i]] );

        //for solid colored faces use 
        //colors.push(vertexColors[a]);    
    }
}

// DEFINE TETRAHEDRON

function colorTetra(){

    var verticesT = [
        vec3(  0.0000,  0.0000, -0.3500 ),
        vec3(  0.0000,  0.3500,  0.1500 ),
        vec3( -0.3500, -0.1500,  0.1500 ),
        vec3(  0.3500, -0.1500,  0.1500 )
    ];

    tetra(verticesT[0], verticesT[1], verticesT[2], verticesT[3]);
}

function makeTetra( a, b, c, color )
{
    // add colors and vertices for one triangle

    var baseColors = [
        vec3(0.7, 0.7, 0.9, 1.0),
        vec3(0.6, 0.8, 0.9, 1.0),
        vec3(0.5, 0.6, 0.9, 1.0),
        vec3(1.0, 1.0, 0.2, 1.0)
    ];

    colors.push( baseColors[color] );
    points.push( a );
    colors.push( baseColors[color] );
    points.push( b );
    colors.push( baseColors[color] );
    points.push( c );
}

function tetra( p, q, r, s )
{
    // tetrahedron with each side using
    // a different color

    makeTetra( p, r, q, 0 );
    makeTetra( p, r, s, 1 );
    makeTetra( p, q, s, 2 );
    makeTetra( q, r, s, 3 );
}


// DEFINE OCTOHEDRON

function colorOcto(){

    var verticesO = [
        vec3(  0.4000, 0.0000, 0.0000 ),        
        vec3(  0.0000, 0.0000, 0.0000 ),
        vec3(  0.0000, 0.4000, 0.0000 ),
        vec3(  0.4000, 0.4000, 0.0000 ),
        vec3(  0.2000, 0.2000, 0.3000 ),
        vec3(  0.2000, 0.2000, -0.3000 )
    ];

    octo(verticesO[0], verticesO[1], verticesO[2], verticesO[3], verticesO[4], verticesO[5]);   
}

function makeOcto( a, b, c, color )
{
    // add colors and vertices for one triangle

    var baseColors = [
        vec3(0.6, 0.6, 0.6, 1.0),
        vec3(0.3, 0.4, 0.9, 1.0),
        vec3(0.9, 0.9, 0.9, 1.0),
    ];

    colorsO.push( baseColors[color] );
    pointsO.push( a );
    colorsO.push( baseColors[color] );
    pointsO.push( b );
    colorsO.push( baseColors[color] );
    pointsO.push( c );
}

function octo( a, b, c, d , e, f)
{
    // tetrahedron with each side using
    // a different color

    makeOcto( a, d, e, 0 );
    makeOcto( a, b, e, 1 );
    makeOcto( b, c, e, 0 );
    makeOcto( c, d, e, 1 );
    makeOcto( a, d, f, 1 );
    makeOcto( a, b, f, 2 );
    makeOcto( b, c, f, 1 );
    makeOcto( c, d, f, 2 );
}

我在这里上传了完整的代码结构:

https://gist.github.com/Carla-de-Beer/10ad7c7309fad48d94df

您需要设置程序,然后在绘制之前为每个模型设置属性和制服。

use program for cube
set attributes for cube
set uniforms for cube
draw cube

use program for tetrahedon
set attributes for tetrahedon
set uniforms for tetrahedon
draw tetrahedon

use program for sphere
set attributes for sphere
set uniforms for sphere
draw sphere
  • 使用程序=gl.useProgram
  • 设置属性=gl.enableVertexAttribArray,gl.vertexAttribPointer
  • 套装制服=gl.uniformXXX,gl.activeTexture+gl.bindTexture

See this answer as well