ritwik sinha ritwik sinha - 7 months ago 15
Javascript Question

WebGL rendering fails when using color buffer



<!doctype html>
<html>

<body>
<canvas id ="ctx" width = "300" height = "300"></canvas>
<script>
//Getting Webgl Context

var ctx = document.getElementById("ctx");
var webgl = ctx.getContext("experimental-webgl");

/*Creating Shader*/

//Vertex Code
var vertexCode =
'attribute vec3 coordinates;'+
'attribute vec3 color;'+
'varying vec3 vColor;'+
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'vColor = color;'+
'}';

//Creating Shader Object
var vertexShader = webgl.createShader(webgl.VERTEX_SHADER);

//Assigning the Source
webgl.shaderSource(vertexShader, vertexCode);

//Compiling the Source
webgl.compileShader(vertexShader);

//Fragment Shader Code
var fragmentCode ='precision mediump float;'+
'varying vec3 vColor;'+
'void main(void) {'+
'gl_FragColor = vec4(vColor, 1.);'+
'}';

//Creating Shader Object
var fragmentShader = webgl.createShader(webgl.FRAGMENT_SHADER);

//Assigning the Source
webgl.shaderSource(fragmentShader, fragmentCode);

//Compiling the Source
webgl.compileShader(fragmentShader);

//Creating Program to store Shader
var shaderProgram = webgl.createProgram();

//Attaching the shaders
webgl.attachShader(shaderProgram, vertexShader);
webgl.attachShader(shaderProgram, fragmentShader);

//linking the Program
webgl.linkProgram(shaderProgram);

//using the Program
webgl.useProgram(shaderProgram);

//Defining geometry
var vertices = [
-0.5,0.5,0.0,
-0.5,-0.5,0.0,
0.5,-0.5,0.0,
0.5,0.5,0.0
];

var colors = [0,0,1, 1,0,0, 0,1,0, 1,0,1,];

indices = [3,2,1,3,1,0];

//Creating a Buffer
var VextexBuffer = webgl.createBuffer();
var IndexBuffer = webgl.createBuffer();
var colorBuffer = webgl.createBuffer();

//Binding the Buffer
webgl.bindBuffer(webgl.ARRAY_BUFFER, VextexBuffer);
webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, IndexBuffer);
webgl.bindBuffer(webgl.ARRAY_BUFFER, colorBuffer);

//Buffer Data
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(vertices), webgl.STATIC_DRAW);
webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), webgl.STATIC_DRAW);
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(colors), webgl.STATIC_DRAW);

/*Associating the shaders to bufferObject*/

//Getting attribute location
var coord = webgl.getAttribLocation(shaderProgram,"coordinates");
var color = webgl.getAttribLocation(shaderProgram, "color");

//pointing an attribute to the currently bound VBO
webgl.vertexAttribPointer(coord, 3, webgl.FLOAT, false ,0,0);
webgl.vertexAttribPointer(color, 3, webgl.FLOAT, false ,0,0);

//enabling the attributes
webgl.enableVertexAttribArray(coord);
webgl.enableVertexAttribArray(color);
//Unbind Array


/*Drawing the Triangle*/

//Clearing the Colour
webgl.clearColor(.5,.5,.5,1);

//Enabling the depth test
webgl.enable(webgl.DEPTH_TEST);

//Clearing colour nuffer bit
webgl.clear(webgl.COLOR_BUFFER_BIT);

//Setting a viewport
webgl.viewport(0,0,ctx.width,ctx.height);

//Draw the triangle
webgl.drawElements(webgl.TRIANGLES,indices.length,webgl.UNSIGNED_SHORT,0);

</script>
</body>
</html>





If I remove colour buffer and everything related to it, the code runs but with colour buffer, I only see gray canvas, nothing else.

Also Chrome console doesn't show any errors or warnings.
Please help me.

Answer

You're overwriting your vertex positions with your colors:

 webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(vertices), webgl.STATIC_DRAW);
 webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(colors), webgl.STATIC_DRAW);

At any given time there can only be one buffer bound for each type (ARRAY_BUFFER and ELEMENT_ARRAY_BUFFER), so the flow is to bind a buffer and set its data followed by setting up the vertex attribute pointers for that specific buffer, then proceed to the next buffer:

// setup positions
var VextexBuffer = webgl.createBuffer();
webgl.bindBuffer(webgl.ARRAY_BUFFER, VextexBuffer);
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(vertices), webgl.STATIC_DRAW);
var coord = webgl.getAttribLocation(shaderProgram,"coordinates");
webgl.vertexAttribPointer(coord, 3, webgl.FLOAT, false ,0,0);

// setup indices
var IndexBuffer = webgl.createBuffer();
webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, IndexBuffer);
webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), webgl.STATIC_DRAW);

// setup colors
var colorBuffer = webgl.createBuffer();
webgl.bindBuffer(webgl.ARRAY_BUFFER, colorBuffer);
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(colors), webgl.STATIC_DRAW);
var color = webgl.getAttribLocation(shaderProgram, "color");
webgl.vertexAttribPointer(color, 3, webgl.FLOAT, false ,0,0);

For applications that work with multiple different buffers and intend to be realtime the flow is to create and set the buffers during initialization phase to then only bind the buffer and set the vertex attribute pointers during the animation loop.

<!doctype html>
<html>

<body>
<canvas id ="ctx" width = "300" height = "300"></canvas> 
    <script>
        //Getting Webgl Context

        var ctx = document.getElementById("ctx");
        var webgl = ctx.getContext("experimental-webgl");

        /*Creating Shader*/

        //Vertex Code
        var vertexCode =
        'attribute vec3 coordinates;'+
        'attribute vec3 color;'+
        'varying vec3 vColor;'+
        'void main(void) {' +
           ' gl_Position = vec4(coordinates, 1.0);' +
           'vColor = color;'+
        '}';

        //Creating Shader Object    
        var vertexShader = webgl.createShader(webgl.VERTEX_SHADER);

        //Assigning the Source
        webgl.shaderSource(vertexShader, vertexCode);

        //Compiling the Source
        webgl.compileShader(vertexShader);

        //Fragment Shader Code 
         var fragmentCode ='precision mediump float;'+
        'varying vec3 vColor;'+
        'void main(void) {'+
           'gl_FragColor = vec4(vColor, 1.);'+
        '}';

        //Creating Shader Object    
        var fragmentShader = webgl.createShader(webgl.FRAGMENT_SHADER);

        //Assigning the Source
        webgl.shaderSource(fragmentShader, fragmentCode);

        //Compiling the Source
        webgl.compileShader(fragmentShader);

        //Creating Program to store Shader
        var shaderProgram = webgl.createProgram();

        //Attaching the shaders
        webgl.attachShader(shaderProgram, vertexShader);
        webgl.attachShader(shaderProgram, fragmentShader);

        //linking the Program
        webgl.linkProgram(shaderProgram);

        //using the Program
        webgl.useProgram(shaderProgram);

        //Defining geometry
        var vertices = [
        -0.5,0.5,0.0,
        -0.5,-0.5,0.0,
        0.5,-0.5,0.0,
        0.5,0.5,0.0
     ];

     var colors = [0,0,1, 1,0,0, 0,1,0, 1,0,1,];

     indices = [3,2,1,3,1,0];

       // setup positions
       var VextexBuffer = webgl.createBuffer();
       webgl.bindBuffer(webgl.ARRAY_BUFFER, VextexBuffer);
       webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(vertices), webgl.STATIC_DRAW);
       var coord = webgl.getAttribLocation(shaderProgram,"coordinates");
       webgl.vertexAttribPointer(coord, 3, webgl.FLOAT, false ,0,0);

       // setup indices
       var IndexBuffer = webgl.createBuffer();
       webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, IndexBuffer);
       webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), webgl.STATIC_DRAW);

       // setup colors
       var colorBuffer = webgl.createBuffer();
       webgl.bindBuffer(webgl.ARRAY_BUFFER, colorBuffer);
       webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(colors), webgl.STATIC_DRAW);
       var color = webgl.getAttribLocation(shaderProgram, "color");
       webgl.vertexAttribPointer(color, 3, webgl.FLOAT, false ,0,0);

        //enabling the attributes
        webgl.enableVertexAttribArray(coord);
        webgl.enableVertexAttribArray(color);
        //Unbind Array


        /*Drawing the Triangle*/

        //Clearing the Colour
        webgl.clearColor(.5,.5,.5,1);

        //Enabling the depth test
        webgl.enable(webgl.DEPTH_TEST);

        //Clearing colour nuffer bit
        webgl.clear(webgl.COLOR_BUFFER_BIT);

        //Setting a viewport
        webgl.viewport(0,0,ctx.width,ctx.height);

        //Draw the triangle
            webgl.drawElements(webgl.TRIANGLES,indices.length,webgl.UNSIGNED_SHORT,0);

    </script>
</body>
</html>

Comments