如何在 WebGL 中绘制两个由顶点着色的三角形?

How can I draw two triangles colored by vertex in WebGL?

我正在尝试解决一个示例问题,该问题要求我绘制两个不同的三角形,每个三角形按顶点着色,如下所示:

我快到了,但似乎有什么不对劲。这是我的结果:

问题是,左边的三角形是我想要的样子:三种颜色,RGB,每个顶点一种。我不知道第二个是怎么得到这些颜色的。我的意图是在其中两个中使用相同的颜色向量 - 尽管如果有人告诉我如何使用两个不同的颜色向量 fColor 我会很感激,这样我就可以为它们中的每一个定义不同的颜色。我不知道直角三角形是如何得到这些颜色的。它们甚至不是我为左边定义的同一组颜色。这是进入 HTML:

的着色器代码
<script id="vertex-shader" type="x-shader/x-vertex">
    # version 300 es

    in vec4 vPosition;
    in vec4 vColor;
    out vec4 fColor;
    void main()
    {
        fColor = vColor;
        gl_Position = vPosition;
    }

</script>

<script id="fragment-shader" type="x-shader/x-fragment">
    # version 300 es

    precision mediump float;

    in vec4 fColor;
    out vec4 fragColor;

    void main()
    {
        fragColor = fColor;
    }

</script>

这里是 javascript:

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

    gl = canvas.getContext('webgl2');
    if (!gl) { alert( "WebGL 2.0 isn't available" ); }

    //
    //  Initialize our data for a single triangle
    //

    // First, initialize the  three points.

    var vertices = [vec3(-1,-1,0),
        vec3(-0.5, 1, 0),
        vec3(0, -1, 0),
        vec3(0,-1,0),
        vec3(0.5, 1, 0),
        vec3(1,-1,0)];

    var colors = [vec3(1,0,0), vec3(0,1,0), vec3(0,0,1)];
    //
    //  Configure WebGL
    //
    gl.viewport( 0, 0, canvas.width, canvas.height );
    gl.clearColor( 1.0, 1.0, 1.0, 1.0 );

    //  Load shaders and initialize attribute buffers

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

    // Load the data into the GPU

    var bufferId = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, bufferId );
    gl.bufferData( gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW );

    // Associate out shader variables with our data buffer

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

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

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

    gl.drawArrays(gl.TRIANGLES, 0, 3);

    // Redefine buffer for the vertices and colors
    var bufferId = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, bufferId );
    gl.bufferData( gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW );

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

    gl.drawArrays(gl.TRIANGLES,3,3);
};

很抱歉代码部分太长了,但我是 GLSL 的新手(javascript/html),我不知道错误在哪里,所以我发布了整个代码。

gl.vertexAttribPointer 指定一个顶点属性数组。它还将当前绑定到 ARRAY_BUFFER 目标的缓冲区与属性相关联。因此,在指定顶点属性时需要确保绑定了正确的缓冲区对象:

gl.bindBuffer( gl.ARRAY_BUFFER, bufferId );
// [...]

gl.vertexAttribPointer( vPosition, 3, gl.FLOAT, false, 0, 0 ); // bufferId is currently bound
// [...]

gl.bindBuffer(gl.ARRAY_BUFFER, cBufferId);
// [...]

gl.vertexAttribPointer( vColor, 3, gl.FLOAT, false, 0, 0 ); // cBufferId is currently bound
// [...]


gl.bindBuffer( gl.ARRAY_BUFFER, bufferId );
gl.bufferData(gl.ARRAY_BUFFER, flatten(colors), gl.STATIC_DRAW);
// [...]

                                                 // bufferId is currently bound
gl.bindBuffer(gl.ARRAY_BUFFER, cBufferId);       // therfore you have to bind cBufferId
gl.vertexAttribPointer( vColor, 3, gl.FLOAT, false, 0, 0 );
// [...]

但是,由于要绘制3到6的顶点,还必须指定3到6的颜色属性:

var colors = [vec3(0,1,0), vec3(1,0,0), vec3(0,1,0),
              vec3(0,0,1), vec3(1,0,0), vec3(0,0,1)];

指定 1 个顶点缓冲区和 1 个颜色缓冲区

var bufferId = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, bufferId );
gl.bufferData( gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW );

// Associate out shader variables with our data buffer

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

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

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

分别画出两个三角形:

gl.drawArrays(gl.TRIANGLES, 0, 3);
gl.drawArrays(gl.TRIANGLES, 3, 6);

或立即

gl.drawArrays(gl.TRIANGLES, 0, 6);