Search code examples
webglwebgl2

varying in webgl is not working as expected


I am new to WebGL and now learning varying variables. In this, my expected output is the image below.

In the code below, I tried to pass colour from the vertex shader to fragment shader.The primitive type pass in drawArray is a triangle but it is not drawing triangles.I wrote this code to understand varying variables in WebGL and is derived from WebGLfundamental website. I don't know what went wrong since from my knowledge, this is what I am supposed to do.

The output I was expecting is :

enter image description here

Code is :

"use strict";

var vs = `#version 300 es

precision highp float;

in vec2 a_position;
in vec4 a_color;

out vec4 v_color;

void main(){
	gl_Position = vec4(a_position, 0, 1);
	v_color = a_color;
}
`;


var fs = `#version 300 es

precision highp float;

in  vec4 v_color;

out vec4 outColor;

void main(){
	outColor = v_color;
}
`;


function main() {
    var canvas = document.querySelector("#c");
    var gl = canvas.getContext("webgl2");
    if (!gl) {
        return;
    }

    var program = webglUtils.createProgramFromSources(gl, [vs, fs]);

    var vertexPosition = gl.getAttribLocation(program, 'a_position');
    var vertexColor = gl.getAttribLocation(program, 'a_color');

    var vao = gl.createVertexArray();
    gl.bindVertexArray(vao);

    var buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);

    var position = [
        -150, -100,
        150, -100,
        -150, 100,
        -150, 100,
        150, -100,
        150, 100
    ];

    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(position), gl.STATIC_DRAW);

    gl.enableVertexAttribArray(vertexPosition);

    var size = 2;
    var type = gl.FLOAT;
    var normalize = false;
    var stride = 0;
    var offset = 0;

    gl.vertexAttribPointer(vertexPosition, size, type, normalize, stride, offset);


    var buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);

    var color = [
        0.7, 0.2, 0.9, 1,
      0.6, 0.7, 0.2, 1,
      0.5, 0.7, 0.9, 1,
      0.4, 0.7, 0.2, 1,
      0.7, 0.2, 0.9, 1,
      0.5, 0.7, 0.9, 1,
    ];

    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(color), gl.STATIC_DRAW);

    gl.enableVertexAttribArray(vertexColor);

    var size =4;
    var type = gl.FLOAT;
    var normalize = false;
    var stride = 0;
    var offset = 0;

    gl.vertexAttribPointer(vertexColor, size, type, normalize, stride, offset);

    webglUtils.resizeCanvasToDisplaySize(gl.canvas);

    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

    gl.clearColor(0, 0, 0, 0);

    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    gl.useProgram(program);

    gl.bindVertexArray(vao);

    var offset = 0;
    var count = 6;
    gl.drawArrays(gl.TRIANGLES, offset, count);

}


main();
 body{
    	overflow: hidden;
    }

    canvas {
        width: 100vw;
        height: 100vh;
        display: block;
    }
<script src="https://webgl2fundamentals.org/webgl/resources/webgl-utils.js"></script>
<canvas id="c">
</canvas>


Solution

  • The issue is you're providing positions in pixels but WebGL requires positions in clip space. So you're drawing what you think you were drawing except only the center 2x2 units of your 300x200 rectangle are being shown.

    For example if we just hack and divide the position by 300,200

    gl_Position = vec4(a_position / vec2(300, 200);
    

    Then it works

    "use strict";
    
    var vs = `#version 300 es
    
    precision highp float;
    
    in vec2 a_position;
    in vec4 a_color;
    
    out vec4 v_color;
    
    void main(){
    	gl_Position = vec4(a_position / vec2(300, 200), 0, 1);
    	v_color = a_color;
    }
    `;
    
    
    var fs = `#version 300 es
    
    precision highp float;
    
    in  vec4 v_color;
    
    out vec4 outColor;
    
    void main(){
    	outColor = v_color;
    }
    `;
    
    
    function main() {
        var canvas = document.querySelector("#c");
        var gl = canvas.getContext("webgl2");
        if (!gl) {
            return;
        }
    
        var program = webglUtils.createProgramFromSources(gl, [vs, fs]);
    
        var vertexPosition = gl.getAttribLocation(program, 'a_position');
        var vertexColor = gl.getAttribLocation(program, 'a_color');
    
        var vao = gl.createVertexArray();
        gl.bindVertexArray(vao);
    
        var buffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    
        var position = [
            -150, -100,
            150, -100,
            -150, 100,
            -150, 100,
            150, -100,
            150, 100
        ];
    
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(position), gl.STATIC_DRAW);
    
        gl.enableVertexAttribArray(vertexPosition);
    
        var size = 2;
        var type = gl.FLOAT;
        var normalize = false;
        var stride = 0;
        var offset = 0;
    
        gl.vertexAttribPointer(vertexPosition, size, type, normalize, stride, offset);
    
    
        var buffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    
        var color = [
            0.7, 0.2, 0.9, 1,
          0.6, 0.7, 0.2, 1,
          0.5, 0.7, 0.9, 1,
          0.4, 0.7, 0.2, 1,
          0.7, 0.2, 0.9, 1,
          0.5, 0.7, 0.9, 1,
        ];
    
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(color), gl.STATIC_DRAW);
    
        gl.enableVertexAttribArray(vertexColor);
    
        var size =4;
        var type = gl.FLOAT;
        var normalize = false;
        var stride = 0;
        var offset = 0;
    
        gl.vertexAttribPointer(vertexColor, size, type, normalize, stride, offset);
    
        webglUtils.resizeCanvasToDisplaySize(gl.canvas);
    
        gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
    
        gl.clearColor(0, 0, 0, 0);
    
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    
        gl.useProgram(program);
    
        gl.bindVertexArray(vao);
    
        var offset = 0;
        var count = 6;
        gl.drawArrays(gl.TRIANGLES, offset, count);
    
    }
    
    
    main();
    body{
        	overflow: hidden;
        }
    
        canvas {
            width: 100vw;
            height: 100vh;
            display: block;
        }
    <script src="https://webgl2fundamentals.org/webgl/resources/webgl-utils.js"></script>
    <canvas id="c">
    </canvas>

    The normal way to convert positions from pixel space to clip space is to use a matrix