WebGL - 更改对象之间的颜色

WebGL - change colours for between objects

我是 WebGL 的新手,想知道如何为不同的对象改变颜色。

我在一个数组中有一个圆和一个字段的数据。我想用绿色显示字段,用蓝色显示字段上的圆圈。

我的 vColor 属性出现错误(不显示我的圈子,只显示字段):
[.Offscreen-For-WebGL-05A18588]GL ERROR :GL_INVALID_OPERATION : glDrawArrays: attempt to access out of range vertices in attribute 1

但是,当我删除设置 vColor 属性的代码时,我可以看到圆圈,但字段和圆圈都显示为黑色。我哪里出错了?

着色器代码:

    <script id="vertex-shader" type="x-shader/x-vertex">
        attribute vec4 vPosition;
        attribute vec4 vColor;
        varying vec4 fColor;

        void main() {
            fColor = vColor;
            gl_Position = vPosition;
        }
    </script>

    <script id="fragment-shader" type="x-shader/x-fragment">
        precision mediump float;
        varying vec4 fColor;

        void main() {
            gl_FragColor = fColor;
        }
    </script>

JS代码:

//cirlce data
var pi = 3.14159;
var x = 2*pi/100;
var y = 2*pi/100;
var r = 0.5;
var center = vec2(0.0, 0.0);
//data for gpu
var vertices = [
    vec2(-7.0,-1),
    vec2(-0.6, 0),
    vec2(0.6, 0),
    vec2(6.0, -1)
];

var vertexColors = [
    vec4( 0.0, 0.0, 0.0, 0.0 ),  // black
    vec4( 1.0, 0.0, 0.0, 0.0 ),  // red
    vec4( 1.0, 1.0, 0.0, 1.0 ),  // yellow
    vec4( 0.0, 1.0, 0.0, 1.0 ),  // green
    vec4( 0.0, 0.0, 1.0, 1.0 ),  // blue
    vec4( 1.0, 0.0, 1.0, 0.0 ),  // magenta
    vec4( 0.0, 1.0, 1.0, 0.0 )   // cyan
];

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

gl = WebGLUtils.setupWebGL( canvas );
if ( !gl ) { alert( "WebGL isn't available" ); }

vertices.push(center);
for(var i = 0; i < 100; i++) {
    vertices.push(add(center, vec2(r*Math.cos(x*i), r*Math.sin(y*i))));
}

console.log(flatten(vertices));

//
//  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 colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, flatten(vertexColors), gl.STATIC_DRAW);    

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

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

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

// Associate out shader variables with our data buffer

render();
};

function render() {
    gl.clear( gl.COLOR_BUFFER_BIT );
    gl.drawArrays( gl.TRIANGLE_FAN, 0, 4);//draw the field - field coordinates start at 0-4
    gl.drawArrays( gl.TRIANGLE_FAN, 5, 100);//draw the circle - circle    coordinates start at 5-100
}

如果您使用顶点颜色作为属性来为您的形状着色,则每个顶点需要一种顶点颜色。换句话说,如果你有 1000 个顶点,每个顶点都需要一个位置和一个颜色。

如果您为每个形状使用固定颜色,那么您可以执行以下操作之一。

  1. 使用常量顶点属性

    // disabling the array means this attribute uses a constant value
    gl.disableVertexAttribArray(vertexColorLocation);
    
    // set the constant value
    gl.vertexAttrib4f(vertexColorLocation, r, g, b, a);
    

    注意:在属性上使用常量值并不常见

  2. 改用制服

    将着色器更改为

    <script id="vertex-shader" type="x-shader/x-vertex">
        attribute vec4 vPosition;
    
        void main() {
            gl_Position = vPosition;
        }
    </script>
    
    <script id="fragment-shader" type="x-shader/x-fragment">
        precision mediump float;
        uniform vec4 fColor;     // <=- changed
    
        void main() {
            gl_FragColor = fColor;
        }
    </script>
    

    现在您可以通过设置 fColor uniform 来设置形状的颜色

    // at init time
    var fColorLocation = gl.getUniformLocation(program, "fColor");
    
    // at render time
    gl.uniform4f(fColorLocation, r, g, b, a);