最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

webgl - Passing color to fragment shader from Javascript - Stack Overflow

programmeradmin2浏览0评论

I am currently learning webgl and have a question. I am trying to make a triangle and passing the color info into fragment shader from js file. The following is my js code:

var VSHADER_SOURCE = 
    'attribute vec4 a_Position;\n'+
    'attribute vec4 a_Color;\n'+
    'varying vec4 v_Color;\n'+
    'void main(){\n'+
        'gl_Position = a_Position;\n'+
        'v_Color = a_Color;\n'+
    '}\n';


var FSHADER_SOURCE = 
    'precision highp float;\n'+
    'varying vec4 v_Color;\n'+
    'void main() {\n'+
        'gl_FragColor = v_Color;\n'+
    '}\n';

function main(){
    var canvas = document.getElementById('webgl');
    var gl = getWebGLContext(canvas);
    if(!gl){
        console.log('Error!');
        return;
    }
    //Init shaders.
    if(!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)){
        console.log('Error!');
        return;
    }
    var vertices = new Float32Array([-0.8, -0.8, 0.8, -0.8, 0.0, 0.8]);
    var color = new Float32Array([0.0, 0.0, 1.0, 1.0]);
    var buffer_object = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer_object);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
    var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(a_Position);

    var color_object = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, color_object);
    gl.bufferData(gl.ARRAY_BUFFER, color, gl.STATIC_DRAW);
    var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
    gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(a_Color);

    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, 3);


    return 0;
}

This have to create a blue triangle but the only thing I see is a canvas filled with black color. Can anyone tell me what's missing?? I created two buffer objects and used one for vertex and the other for color.

I am currently learning webgl and have a question. I am trying to make a triangle and passing the color info into fragment shader from js file. The following is my js code:

var VSHADER_SOURCE = 
    'attribute vec4 a_Position;\n'+
    'attribute vec4 a_Color;\n'+
    'varying vec4 v_Color;\n'+
    'void main(){\n'+
        'gl_Position = a_Position;\n'+
        'v_Color = a_Color;\n'+
    '}\n';


var FSHADER_SOURCE = 
    'precision highp float;\n'+
    'varying vec4 v_Color;\n'+
    'void main() {\n'+
        'gl_FragColor = v_Color;\n'+
    '}\n';

function main(){
    var canvas = document.getElementById('webgl');
    var gl = getWebGLContext(canvas);
    if(!gl){
        console.log('Error!');
        return;
    }
    //Init shaders.
    if(!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)){
        console.log('Error!');
        return;
    }
    var vertices = new Float32Array([-0.8, -0.8, 0.8, -0.8, 0.0, 0.8]);
    var color = new Float32Array([0.0, 0.0, 1.0, 1.0]);
    var buffer_object = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer_object);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
    var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(a_Position);

    var color_object = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, color_object);
    gl.bufferData(gl.ARRAY_BUFFER, color, gl.STATIC_DRAW);
    var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
    gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(a_Color);

    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, 3);


    return 0;
}

This have to create a blue triangle but the only thing I see is a canvas filled with black color. Can anyone tell me what's missing?? I created two buffer objects and used one for vertex and the other for color.

Share Improve this question edited Jul 29, 2021 at 20:20 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Oct 1, 2014 at 4:22 eChung00eChung00 6311 gold badge12 silver badges27 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 7

There's a lot of issues with your example but... specific problems.

You're only supplying colors for the first vertex.

You have 3 vertices but only 1 color. You should be getting an error for that. Did you check the JavaScript Console for errors?

You have 3 options to fix that

  1. Provide a color for each vertex

    new Float32Array([
      0.0, 0.0, 1.0, 1.0,
      0.0, 0.0, 1.0, 1.0,
      0.0, 0.0, 1.0, 1.0,
    ]);
    
  2. Turn off the a_Color attribute and supply a constant value

    gl.disableVertexAtttibArray(a_Color);
    gl.vertexAttrib4f(a_Color, 0, 0, 1, 1);
    
  3. Use a uniform instead of an attribute + varying

    remove all references of a_Color and v_color and instead have your fragment shader be

    precision highp float;
    uniform vec4 u_Color;
    void main() {
      gl_FragColor = u_Color;
    }
    

    Now you'd set the color with

    At Init time

    // Lookup the location
    var u_colorLocation = gl.getUniformLocation(program, "u_Color");
    

    At render time

    // Set the uniform
    gl.uniform4f(u_colorLocation, 0, 0, 1, 1);
    

If you choose #2 you'll likely run into another issue that you'll get a warning that attirbute 0 is not enabled because, at least on my puter, a_Color is assigned to attribute 0. Turning it off means it has to be emulated which is slow. The solution is to make sure a_Position is in attribute 0 by calling gl.bindAttribLocation before linking the program.

Other issues:

Your initShader function is apparently creating a program and attaching it to the WebGLRenderContext (gl.program). Most WebGL projects have many shader programs so it would probably be best to just return the program. In other words, instead of

initShader(...);
gl.getAttribLocation(gl.program, ...)

You probably want

var program = initShader(...);
gl.getAttribLocation(program, ...)

You'll need to fix initShader so it returns the program that was created rather than hacking it on to the WebGLRenderingContext.

Also you're using precision highp float. That won't work on many phones. Unless you're sure you need highp it's better to use mediump.

发布评论

评论列表(0)

  1. 暂无评论