Instanced line drawing with normals in WebGL2

Viewed 7

I'm trying to learn how to draw basic thick 2D lines in WebGL2, with the help of instancing and normals.

Codepen

I'm trying to follow the instructions here, the very first example that begins with "Basic instanced line rendering". But I'm doing it without Regl.

Basic components:

  • position attribute - a basic shape (two triangles), identical for every instance
  • pointA and pointB attributes - the line endpoints, changes between instances
  • width uniform - half the width should be added on each side of the line

For the sake of simplicity, I have removed the projection matrix and some other components that I believe are not strictly needed.

I have a feeling I'm missing something obvious, because I'm not getting any results on the screen. I have gone over the calculation in the vertex shader, the coordinates, offsets, strides, etc, but not been able to find the issue. Maybe I just don't understand instancing very well. It's quite difficult to troubleshoot when you don't get any error messages.

Any help would be appreciated.

// Shaders

const vertexShaderSrc = `
    precision highp float;
    uniform float width;
    attribute vec2 position;
    attribute vec2 pointA;
    attribute vec2 pointB;
        
    void main() {
        vec2 xBasis = pointB - pointA;
        vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x));
        vec2 point = pointA + xBasis * position.x + yBasis * width * position.y;
        gl_Position = vec4(point, 0, 1);
    }`;

const fragmentShaderSrc = `
    precision highp float;

    void main() {
        gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
    }`;


// Setup program with shaders

const gl = document.qetElementById('canvas').getContext('webgl2');
const program = gl.createProgram();

const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSrc);
gl.compileShader(vertexShader);
gl.attachShader(program, vertexShader);

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSrc);
gl.compileShader(fragmentShader);
gl.attachShader(program, fragmentShader);

gl.linkProgram(program);

if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    console.log(gl.getShaderInfoLog(vertexShader));
    console.log(gl.getShaderInfoLog(fragmentShader));
}
gl.useProgram(program);


// Geometry:

const geometryData = new Float32Array([
    // Triangle 1
    0, -0.5,
    1, -0.5,
    1, 0.5,
    // Triangle 2
    0, -0.5,
    1, 0.5,
    0, 0.5
    ]);

// End points:

const pointsData = new Float32Array([
    // pointA     pointB
    -0.2,0.7,   0.3,-0.5,
    0.3,-0.5,   -0.2,0.7,
]);


// Setup data for rendering:

function main() {
    const positionLoc = gl.getAttribLocation(program, 'position');
    const pointALoc = gl.getUniformLocation(program, 'pointA');
    const pointBLoc = gl.getUniformLocation(program, 'pointB');
    const widthLoc = gl.getUniformLocation(program, 'width');

    const geometryBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, geometryBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, geometryData, gl.STATIC_DRAW);
    gl.vertexAttribPointer(
        positionLoc, // attribute
        2,           // size
        gl.FLOAT,    // type
        false,       // normalize
        16,          // stride
        0);          // offset

    gl.vertexAttribDivisor(positionLoc, 0);
    gl.enableVertexAttribArray(positionLoc);

    const pointsBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, pointsBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, pointsData, gl.STATIC_DRAW);

    gl.vertexAttribPointer(
        pointALoc, // attribute
        2,         // size
        gl.FLOAT,  // type
        false,     // normalize
        16,        // stride
        0);        // offset

    gl.vertexAttribPointer(
        pointBLoc, // attribute
        2,         // size
        gl.FLOAT,  // type
        false,     // normalize
        16,        // stride
        8);        // offset

    gl.vertexAttribDivisor(pointALoc, 1);
    gl.vertexAttribDivisor(pointBLoc, 1);

    gl.enableVertexAttribArray(pointALoc);
    gl.enableVertexAttribArray(pointBLoc);

    gl.uniform1f(widthLoc, 4) // line thickness

    gl.drawArraysInstanced(
        gl.TRIANGLES, // method
        0,            // offset
        6,            // number of vertices per instance
        2);           // number of instances
}

main();
0 Answers
Related