Search code examples
javascriptglslshaderwebgl

webgl trying to draw a triangle


I have been trying to draw a triangle but it is not showing up on the canvas

here is my draw function code:

function draw() {
    gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight)gl.clear(gl.COLOR_BUFFER_BIT)       
    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 
                buffer.itemSize, gl.FLOAT, false, 0, 0); 
    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute)
      
        //Draw the triangle
    gl.drawArrays(gl.TRIANGLES, 0, buffer.numberOfItems)
}

here is the whole work:

const vertexShaderText = [
  'attribute vec3 vertexPos;',
  '',
  'void main() {',
  '  gl_Position = vec4(vertexPos, 1.0);',
  '}'
].join('\n')

const fragmentShaderText = [
  'precision mediump float;',
  '',
  'void main() {',
  '  gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);',
  '}'
].join('\n')

let gl, shaderProgram, buffer

function startup() {
  const canvas = document.getElementById('myCanvas')
  gl = canvas.getContext('webgl')

  initShader()
  initBuffer()

  gl.clearColor(0.0, 0.0, 0.0, 1.0)

  draw()
}

function initShader() {

  // VERTEX SHADER
  let vertexShader = gl.createShader(gl.VERTEX_SHADER)
  gl.shaderSource(vertexShader, vertexShaderText)
  gl.compileShader(vertexShader)

  if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
    alert('vertex', gl.getShaderInfoLog(vertexShader))
    return
  }

  let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
  gl.shaderSource(fragmentShader, fragmentShaderText)
  gl.compileShader(fragmentShader)

  if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
    alert('fragment', gl.getShaderInfoLog(fragmentShader))
    return
  }


  shaderProgram = gl.createProgram()

  gl.attachShader(shaderProgram, vertexShader)
  gl.attachShader(shaderProgram, fragmentShader)

  gl.linkProgram(shaderProgram)

  if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
    alert('Failed to setup shaders')
  }

  gl.useProgram(shaderProgram)

  shaderProgram.vertextPositionAttribute = gl.getAttribLocation(shaderProgram, 'vertexPos')
  //gl.enableVertexAttribArray(shaderProgram.vertextPositionAttribute)

}

function initBuffer() {
  buffer = gl.createBuffer()

  gl.bindBuffer(gl.ARRAY_BUFFER, buffer)

  const triangleVertices = [
    0.0, 0, 5, 0.0, -0.5, -0.5, 0.0,
    0.5, -0.5, 0.0
  ]

  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW)

  buffer.itemSize = 3
  buffer.numberOfItems = 3
  console.log(shaderProgram)
}

function draw() {
  gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight) 
  gl.clear(gl.COLOR_BUFFER_BIT)

  gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
    buffer.itemSize, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute)  
  //Draw the triangle
  gl.drawArrays(gl.TRIANGLES, 0, buffer.numberOfItems)
}

startup()
<canvas id="myCanvas" width="500" height="500"></canvas>


Solution

  • There are some issues:

    The properties gl.viewportWidth and gl.viewportHeight are never set:

    gl = canvas.getContext('webgl')
    gl.viewportWidth = canvas.clientWidth;
    gl.viewportHeight = canvas.clientHeight;
    

    In the array of vertex coordinates is a , instead of a .

    const triangleVertices = [
         0.0,  0,5, 0.0, // <---- this line
        -0.5, -0.5, 0.0, 
         0.5, -0.5, 0.0
    ]
    

    And there is a typo , you wrote vertextPositionAttribute instead of vertexPositionAttribute, when you get the attribute index:

    shaderProgram.vertextPositionAttribute = // <--- typo
        gl.getAttribLocation(shaderProgram, 'vertexPos') 
    

    But in general your code works:

      const vertexShaderText = [
        'attribute vec3 vertexPos;',
        '',
        'void main() {',
        '  gl_Position = vec4(vertexPos, 1.0);',
        '}'
    ].join('\n')
    
    const fragmentShaderText = [
        'precision mediump float;',
        '',
        'void main() {',
        '  gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);',
        '}'
    ].join('\n')
    
    let gl, shaderProgram, buffer
    
    function startup() {
        const canvas = document.getElementById('myCanvas')
        gl = canvas.getContext('webgl')
    
        gl.viewportWidth = canvas.clientWidth;
        gl.viewportHeight = canvas.clientHeight;
          
        initShader()
        initBuffer()
    
        gl.clearColor(0.0, 0.0, 0.0, 1.0)
        
        draw()
    }
    
    function initShader() {
        
        // VERTEX SHADER
        let vertexShader = gl.createShader(gl.VERTEX_SHADER)
        gl.shaderSource(vertexShader, vertexShaderText)
        gl.compileShader(vertexShader)
    
        if(!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
            alert('vertex', gl.getShaderInfoLog(vertexShader))
            return
        }
    
        let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
        gl.shaderSource(fragmentShader, fragmentShaderText)
        gl.compileShader(fragmentShader)
    
        if(!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
            alert('fragment', gl.getShaderInfoLog(fragmentShader))
            return
        }
        
    
        shaderProgram = gl.createProgram()
    
        gl.attachShader(shaderProgram, vertexShader )
        gl.attachShader(shaderProgram, fragmentShader)
    
        gl.linkProgram(shaderProgram)
    
        if(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
            alert('Failed to setup shaders')
        }
    
        gl.useProgram(shaderProgram)
    
        shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, 'vertexPos')
        //gl.enableVertexAttribArray(shaderProgram.vertextPositionAttribute)
      
    }
    
    function initBuffer() {
        buffer = gl.createBuffer()
    
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
    
        const triangleVertices = [
              0.0,  0.5, 0.0,
            -0.5, -0.5, 0.0,
              0.5, -0.5, 0.0
        ]
    
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW)
    
        buffer.itemSize = 3
        buffer.numberOfItems = 3
        console.log(shaderProgram)
    }
    
    function draw() {
        gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight)
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 
        
        gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 
                buffer.itemSize, gl.FLOAT, false, 0, 0); 
        gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
    
        //Draw the triangle
        gl.drawArrays(gl.TRIANGLES, 0, buffer.numberOfItems)
    
        requestAnimationFrame(draw);
    }
    
    startup()
    <canvas id="myCanvas" width="500" height="500"></canvas>