WebGL - 更改对象之间的颜色

时间:2017-02-19 09:13:41

标签: javascript colors webgl

我是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
}

1 个答案:

答案 0 :(得分:1)

如果您使用顶点颜色作为颜色来为您的形状着色,则需要一个顶点颜色PER顶点。换句话说,如果你有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);