Search code examples
shaderwebgl2

webgl why I get errors when I use version 300 in shaders


I am making webgl app. I want to use version 300 es in my shader, I am sure that browser supports this version but I get some errors when I try to use.

This is my code.

var VertexShaderCode = `
    #version 300 es
    precision mediump float;
    in vec3 vertexPos;
    uniform vec2 orthoValues;
    in vec2 offset;
    mat4 curProjMat=mat4(vec4(0.0),vec4(0.0),0.0,0.0,-0.05,0.0,-1.0,1.0,0.0,1.0);

    void main(void) {
      curProjMat[0][0] = 2.0  /  orthoValues.x;
      curProjMat[1][1] = -2.0  / orthoValues.y;
      gl_Position= curProjMat*vec4(vertexPos.x+offset.x, vertexPos.y+offset.y, 1.0, 1.0);
    }`
    var vertexShader = gl.createShader(gl.VERTEX_SHADER)
    gl.shaderSource(vertexShader, VertexShaderCode)
    gl.compileShader(vertexShader)

    var FragmentShaderCode = 
     `#version 300 es
      precision lowp float;
      out vec4 outColor;

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


    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
    gl.shaderSource(fragmentShader, FragmentShaderCode)
    gl.compileShader(fragmentShader)
    var shaderProgram = gl.createProgram()
    gl.attachShader(shaderProgram, vertexShader)
    gl.attachShader(shaderProgram, fragmentShader)
    gl.linkProgram(shaderProgram)
    return shaderProgram

Then I assign this shader in constructor.

  gl.useProgram(this.Program2D)
  this.P2DvertexPos = gl.getAttribLocation(this.Program2D, 'vertexPos')
  this.P2DoffsetLoc=gl.getAttribLocation(this.Program2D, 'offset')
  this.P2DOrtoValues = gl.getUniformLocation(this.Program2D, 'orthoValues')

as soon as I assign this, I get these errors.

INVALID_OPERATION: useProgram: program not valid
`INVALID_OPERATION: getAttribLocation: program not linked`
INVALID_OPERATION: getUniformLocation: program not linked

Solution

  • When compiling shaders and linking programs you should check if things were successful and if not then print the errors.

    For shaders after you compile a shader you call

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      // there was an error
      console.error(gl.getShaderInfoLog(shader));
     ...
    
    

    for programs after you link the program you call

    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
      // there was an error
      console.error(gl.getProgramInfoLog(program));
     ...
    
    

    Adding that you start getting told what the problems are

    const gl = document.createElement('canvas').getContext('webgl2');
    if (!gl) alert('need webgl2');
    
    var VertexShaderCode = `
        #version 300 es
        precision mediump float;
        in vec3 vertexPos;
        uniform vec2 orthoValues;
        in vec2 offset;
        mat4 curProjMat=mat4(vec4(0.0),vec4(0.0),0.0,0.0,-0.05,0.0,-1.0,1.0,0.0,1.0);
    
        void main(void) {
          curProjMat[0][0] = 2.0  /  orthoValues.x;
          curProjMat[1][1] = -2.0  / orthoValues.y;
          gl_Position= curProjMat*vec4(vertexPos.x+offset.x, vertexPos.y+offset.y, 1.0, 1.0);
        }`
        var vertexShader = gl.createShader(gl.VERTEX_SHADER)
        gl.shaderSource(vertexShader, VertexShaderCode)
        gl.compileShader(vertexShader)
        if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
          // there was an error
          console.error(gl.getShaderInfoLog(vertexShader));
        }
    
        var FragmentShaderCode = 
         `#version 300 es
          precision lowp float;
          out vec4 outColor;
    
          void main() {
            outColor = vec4(1.0,1.0,1.0,1.0);
          }
         `
    
    
        var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
        gl.shaderSource(fragmentShader, FragmentShaderCode)
        gl.compileShader(fragmentShader)
        if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
          // there was an error
          console.error(gl.getShaderInfoLog(fragmentShader));
        }
        
        
        var shaderProgram = gl.createProgram()
        gl.attachShader(shaderProgram, vertexShader)
        gl.attachShader(shaderProgram, fragmentShader)
        gl.linkProgram(shaderProgram)
        if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
          // there was an error
          console.error(gl.getProgramInfoLog(shaderProgram));
        }
        
    //    return shaderProgram

    Once you do that it will tell you #version 300 es is required to be the first line but for your vertex shader it was not the first line, there was a blank line before it.

    const gl = document.createElement('canvas').getContext('webgl2');
    if (!gl) alert('need webgl2');
    
    var VertexShaderCode = `#version 300 es
        precision mediump float;
        in vec3 vertexPos;
        uniform vec2 orthoValues;
        in vec2 offset;
        mat4 curProjMat=mat4(vec4(0.0),vec4(0.0),0.0,0.0,-0.05,0.0,-1.0,1.0,0.0,1.0);
    
        void main(void) {
          curProjMat[0][0] = 2.0  /  orthoValues.x;
          curProjMat[1][1] = -2.0  / orthoValues.y;
          gl_Position= curProjMat*vec4(vertexPos.x+offset.x, vertexPos.y+offset.y, 1.0, 1.0);
        }`
        var vertexShader = gl.createShader(gl.VERTEX_SHADER)
        gl.shaderSource(vertexShader, VertexShaderCode)
        gl.compileShader(vertexShader)
        if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
          // there was an error
          console.error(gl.getShaderInfoLog(vertexShader));
        }
    
        var FragmentShaderCode = 
         `#version 300 es
          precision lowp float;
          out vec4 outColor;
    
          void main() {
            outColor = vec4(1.0,1.0,1.0,1.0);
          }
         `
    
    
        var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
        gl.shaderSource(fragmentShader, FragmentShaderCode)
        gl.compileShader(fragmentShader)
        if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
          // there was an error
          console.error(gl.getShaderInfoLog(fragmentShader));
        }
        
        
        var shaderProgram = gl.createProgram()
        gl.attachShader(shaderProgram, vertexShader)
        gl.attachShader(shaderProgram, fragmentShader)
        gl.linkProgram(shaderProgram)
        if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
          // there was an error
          console.error(gl.getProgramInfoLog(shaderProgram));
        }
        
    //    return shaderProgram

    You might find these articles useful. They cover checking for errors in the very first article. It's surprising wherever you learned this wasn't one of the first things covered.