Home > Back-end >  Why isn't this drawing a triangle?
Why isn't this drawing a triangle?

Time:10-11

I don't know why my WebGL code is not drawing a simple triangle on the screen and I'm not sure how to debug it. The shaders are able to compile so I believe that's not the problem.

main.js:

const canvas = document.querySelector("#gl-canvas")
const gl = canvas.getContext('webgl2')

const consoleShaderCompilationErrors = (name, shader) => {
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.log(`${name} debug:`, gl.getShaderInfoLog(shader))
    }
}

const vertexData = [
    0, 0,
    -0.5, 0.5,
    0.5, 0.5
]

const vertexDataBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, vertexDataBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW)


const vertexShader = gl.createShader(gl.VERTEX_SHADER)
gl.shaderSource(vertexShader, `
    attribute vec3 position;

    void main() {
        gl_Position = vec4(position, 1);
    }

`)
gl.compileShader(vertexShader)
consoleShaderCompilationErrors("vertexShader", vertexShader)

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(fragmentShader, `
    void main() {
        gl_FragColor = vec4(1, 1, 1, 1);
    }
`)
gl.compileShader(fragmentShader)
consoleShaderCompilationErrors("fragmentShader", fragmentShader)

const program = gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program)

const positionLocation = gl.getAttribLocation(program, "position")
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(positionLocation)


gl.drawArrays(gl.LINES, 0, 3)

index.html:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Prod WebGL</title>
    <style>
        #gl-canvas {
            border: 1px solid black;
        }
    </style>
    <script src="./main.js" defer></script>
</head>
<body>
    <canvas id="gl-canvas" width="400" height="400"></canvas>
</body>
</html>

Can you point me in the right direction? I have been trying to figure out the problems for hours now...

CodePudding user response:

Use gl.LINE_LOOP instead of gl.LINES:

gl.drawArrays(gl.LINES, 0, 3)

gl.drawArrays(gl.LINE_LOOP, 0, 3)

gl.LINES is for line segments, where 2 vertices define a line. gl.LINE_LOOP is for a line strip with a connection from the last to the first vertex. See Primitives.


You need to create a Vertex Array Object when you using a WebGL 2.0 context:

let vao = gl.createVertexArray();
gl.bindVertexArray(vao);
const vertexDataBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, vertexDataBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW)

Actually you are drawing a white rectangle on a white background. Change the color in the fragment shader:

void main() {
    gl_FragColor = vec4(1, 0, 0, 1);
}

const canvas = document.querySelector("#gl-canvas")
const gl = canvas.getContext('webgl2')

const consoleShaderCompilationErrors = (name, shader) => {
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.log(`${name} debug:`, gl.getShaderInfoLog(shader))
    }
}

const vertexData = [
    0, 0,
    -0.5, 0.5,
    0.5, 0.5
]

let vao = gl.createVertexArray();
gl.bindVertexArray(vao);
const vertexDataBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, vertexDataBuffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW)


const vertexShader = gl.createShader(gl.VERTEX_SHADER)
gl.shaderSource(vertexShader, `
    attribute vec3 position;

    void main() {
        gl_Position = vec4(position, 1);
    }

`)
gl.compileShader(vertexShader)
consoleShaderCompilationErrors("vertexShader", vertexShader)

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(fragmentShader, `
    void main() {
        gl_FragColor = vec4(1, 0, 0, 1);
    }
`)
gl.compileShader(fragmentShader)
consoleShaderCompilationErrors("fragmentShader", fragmentShader)

const program = gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
gl.useProgram(program)

const positionLocation = gl.getAttribLocation(program, "position")
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(positionLocation)

gl.drawArrays(gl.LINE_LOOP, 0, 3)
#gl-canvas {
    border: 1px solid black;
}
<canvas id="gl-canvas" width="400" height="400"></canvas>

  • Related