javascriptwebglframebufferwebgl2

GL_INVALID_OPERATION: Only array uniforms may have count > 1. Framebuffer in webgl2


enter image description here

I got it spot light.

I cut most interest part of code. it almost all there related with framebuffer:

 App.operation.draws.drawSquareTex = function(object) {
  var lighting = true;
  // eslint-disable-next-line no-unused-vars
  var localLooper = 0;

  mat4.identity(object.mvMatrix);
  this.mvPushMatrix(object.mvMatrix, this.mvMatrixStack);

  if (object.isHUD === true) {

    mat4.translate(object.mvMatrix, object.mvMatrix, object.position.worldLocation);
    if(raycaster.checkingProcedureCalc) raycaster.checkingProcedureCalc(object);

  } else {

    if(App.camera.FirstPersonController == true) {
      camera.setCamera(object);
    } else if(App.camera.SceneController == true) {
      camera.setSceneCamera(object);
    }

    mat4.translate(object.mvMatrix, object.mvMatrix, object.position.worldLocation);
    if(raycaster.checkingProcedureCalc) raycaster.checkingProcedureCalc(object);
    mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(object.rotation.rz), object.rotation.getRotDirZ());
    mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(object.rotation.rx), object.rotation.getRotDirX());
    mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(object.rotation.ry), object.rotation.getRotDirY());
  }

  // V
  if(object.vertexPositionBuffer) {
    world.GL.gl.bindBuffer(world.GL.gl.ARRAY_BUFFER, object.vertexPositionBuffer);

    if(object.geometry.dynamicBuffer == true) {
      world.GL.gl.bufferData(world.GL.gl.ARRAY_BUFFER, object.geometry.vertices, world.GL.gl.STATIC_DRAW);
    }

    world.GL.gl.vertexAttribPointer(object.shaderProgram.vertexPositionAttribute, object.vertexPositionBuffer.itemSize, world.GL.gl.FLOAT, false, 0, 0);
    world.GL.gl.enableVertexAttribArray(object.shaderProgram.vertexPositionAttribute);
    localLooper = localLooper + 1;
  }

  // C
  if(object.vertexColorBuffer) {
    world.GL.gl.bindBuffer(world.GL.gl.ARRAY_BUFFER, object.vertexColorBuffer);
    world.GL.gl.vertexAttribPointer(object.shaderProgram.vertexColorAttribute, object.vertexColorBuffer.itemSize, world.GL.gl.FLOAT, false, 0, 0);
    world.GL.gl.enableVertexAttribArray(object.shaderProgram.vertexColorAttribute);
    localLooper = localLooper + 1;
  }

  // L
  if(lighting && object.shaderProgram.useLightingUniform) {
    world.GL.gl.uniform1i(object.shaderProgram.useLightingUniform, lighting);
    /* Set the normals */
    if(object.vertexNormalBuffer) {
      world.GL.gl.bindBuffer(world.GL.gl.ARRAY_BUFFER, object.vertexNormalBuffer);
      world.GL.gl.vertexAttribPointer(object.shaderProgram.vertexNormalAttribute, object.vertexNormalBuffer.itemSize, world.GL.gl.FLOAT, false, 0, 0);
      world.GL.gl.enableVertexAttribArray(object.shaderProgram.vertexNormalAttribute);
      localLooper = localLooper + 1;
    }

    /* Ambient light - posible deplaced */
    if(object.shaderProgram.ambientColorUniform) {
      if(E('ambLight') && E('ambLight').color) {
        world.GL.gl.uniform3f(object.shaderProgram.ambientColorUniform, parseFloat(E('ambLight').color.rgb[0]), parseFloat(E('ambLight').color.rgb[1]), parseFloat(E('ambLight').color.rgb[2]));
      } else {
        world.GL.gl.uniform3f(object.shaderProgram.ambientColorUniform, object.LightsData.ambientLight.r, object.LightsData.ambientLight.g, object.LightsData.ambientLight.b);
      }
    }

    /* Directional light */
    if(object.shaderProgram.directionalColorUniform) {
      if(E('dirLight') && E('dirLight').color) {
        world.GL.gl.uniform3f(object.shaderProgram.directionalColorUniform, parseFloat(E('dirLight').color.rgb[0]), parseFloat(E('dirLight').color.rgb[1]), parseFloat(E('dirLight').color.rgb[2]));
      } else {
        world.GL.gl.uniform3f(object.shaderProgram.directionalColorUniform, object.LightsData.directionLight.R(), object.LightsData.directionLight.G(), object.LightsData.directionLight.B());
      }
    }

    /* Normalize the direction */
    var lightingDirection = null;
    if(object.shaderProgram.lightingDirectionUniform) {
      if(E('dirX') && E('dirY') && E('dirZ')) {
        lightingDirection = [parseFloat(E('dirX').value), parseFloat(E('dirY').value), parseFloat(E('dirZ').value)];
      } else {
        lightingDirection = [object.LightsData.lightingDirection.r, object.LightsData.lightingDirection.g, object.LightsData.lightingDirection.b];
      }

      var adjustedLD = vec3.create();
      vec3.normalize(adjustedLD, lightingDirection);
      vec3.scale(adjustedLD, adjustedLD, -1);
      world.GL.gl.uniform3fv(object.shaderProgram.lightingDirectionUniform, adjustedLD);
    }
  } else {
    if(object.shaderProgram.useLightingUniform) {
      if(object.shaderProgram.ambientColorUniform) {
        world.GL.gl.uniform3f(object.shaderProgram.ambientColorUniform, parseFloat(1), parseFloat(2), parseFloat(0));
      }
      if(object.shaderProgram.directionalColorUniform) {
        world.GL.gl.uniform3f(object.shaderProgram.directionalColorUniform, parseFloat(1), parseFloat(0), parseFloat(0));
      }
    }
  }

  // T
  if(object.vertexTexCoordBuffer) {
    world.GL.gl.bindBuffer(world.GL.gl.ARRAY_BUFFER, object.vertexTexCoordBuffer);

    if(object.geometry.dynamicBuffer == true) {
      world.GL.gl.bufferData(world.GL.gl.ARRAY_BUFFER, object.geometry.texCoords, world.GL.gl.STATIC_DRAW);
    }

    world.GL.gl.vertexAttribPointer(object.shaderProgram.textureCoordAttribute, object.vertexTexCoordBuffer.itemSize, world.GL.gl.FLOAT, false, 0, 0);
    world.GL.gl.enableVertexAttribArray(object.shaderProgram.textureCoordAttribute);

    if(object.streamTextures != null) {
      // video/webcam tex
      // App.tools.loadVideoTexture('glVideoTexture', object.streamTextures.videoImage);
      App.tools.loadVideoTexture('glVideoTexture', object.streamTextures.video);
      world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, 0);
    } else {
      for(var t = 0;t < object.textures.length;t++) {
        if(object.custom.gl_texture == null) {
          world.GL.gl.activeTexture(world.GL.gl['TEXTURE' + t]);
          world.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.textures[t]);

          world.GL.gl.pixelStorei(world.GL.gl.UNPACK_FLIP_Y_WEBGL, false);
          world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MAG_FILTER, world.GL.gl.NEAREST);

          world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MIN_FILTER, world.GL.gl.NEAREST);
          world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_S, world.GL.gl.CLAMP_TO_EDGE);
          world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_T, world.GL.gl.CLAMP_TO_EDGE);
          // -- Allocate storage for the texture
          //world.GL.gl.texStorage2D(world.GL.gl.TEXTURE_2D, 1, world.GL.gl.RGB8, 512, 512);
          //world.GL.gl.texSubImage2D(world.GL.gl.TEXTURE_2D, 0, 0, 0, world.GL.gl.RGB, world.GL.gl.UNSIGNED_BYTE, image);
          //world.GL.gl.generateMipmap(world.GL.gl.TEXTURE_2D);
          // ori world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, t);
          // var nothing = 

          // world.GL.gl.uniform1i(object.shaderProgram['samplerUniform' + t], t);
          world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, t);

        } else {
          object.custom.gl_texture(object, t);
        }
      }
    }

    localLooper = localLooper + 1;
  }

  world.GL.gl.bindBuffer(world.GL.gl.ELEMENT_ARRAY_BUFFER, object.vertexIndexBuffer);
  world.setMatrixUniforms(object, this.pMatrix, object.mvMatrix);

  if(object.vertexNormalBuffer && object.shaderProgram.nMatrixUniform) {
    var normalMatrix = mat3.create();
    mat3.normalFromMat4(normalMatrix, object.mvMatrix);
    mat3.transpose(normalMatrix, normalMatrix);
    world.GL.gl.uniformMatrix3fv(object.shaderProgram.nMatrixUniform, false, normalMatrix);
  }

  // world.disableUnusedAttr( world.GL.gl, localLooper);
  world.disableUnusedAttr(world.GL.gl, 4);

  if(object.glBlend.blendEnabled == true) {
    if(!world.GL.gl.isEnabled(world.GL.gl.BLEND)) {
      // world.GL.gl.disable(world.GL.gl.DEPTH_TEST);
      world.GL.gl.enable(world.GL.gl.BLEND);
    }
    try {
      world.GL.gl.blendFunc(world.GL.gl[object.glBlend.blendParamSrc], world.GL.gl[object.glBlend.blendParamDest]);
    } catch(e) {
      console.log(e);
    }
  } else {
    world.GL.gl.disable(world.GL.gl.BLEND);
    world.GL.gl.enable(world.GL.gl.DEPTH_TEST);

    world.GL.gl.enable(world.GL.gl.CULL_FACE);
  }

  // shadows
  if(object.shadows && object.shadows.type == 'spot' ||
     object.shadows.type == 'spot-shadow') {



      const settings = {
        cameraX: 6,
        cameraY: 5,
        posX: 2.5,
        posY: 4.8,
        posZ: 4.3,
        targetX: 2.5,
        targetY: 0,
        targetZ: 3.5,
        projWidth: 1,
        projHeight: 1,
        perspective: true,
        fieldOfView: 120,
        bias: -0.006,
      };


      if (!object.shadows.depthFramebuffer) {
        console.log('ONLY ONCE !!!')
        var depthFramebuffer =  depthTextures(world.GL.gl);
        object.shadows.depthFramebuffer = depthFramebuffer[0];
        object.shadows.TEST = depthFramebuffer[1];
      }


    // console.log(" SHADOWS -> " , object.shadows)
    // set the light position
    world.GL.gl.uniform3fv(object.shaderProgram.lightWorldPositionLocation, object.shadows.lightPosition);
    // set the camera/view position
    // gl.uniform3fv(object.shaderProgram.viewWorldPositionLocation, camera);
    // world.GL.gl.uniform3fv(object.shaderProgram.viewWorldPositionLocation, [matrixEngine.Events.camera.xPos, matrixEngine.Events.camera.yPos, matrixEngine.Events.camera.zPos]);
    world.GL.gl.uniform3fv(object.shaderProgram.viewWorldPositionLocation, object.shadows.lightPosition);
    // Set the shininess
    world.GL.gl.uniform1f(object.shaderProgram.shininessLocation, object.shadows.shininess);
    // Set the spotlight uniforms
    {
      var target = [0, 0, 0]; // object.position.worldLocation;
      var up = [0, 1, 0];
      var lmat = m4.lookAt(object.shadows.lightPosition, target, up);
      // var lmat = m4.lookAt(object.position.worldLocation, target, up);
      lmat = m4.multiply(m4.xRotation(object.shadows.lightRotationX), lmat);
      lmat = m4.multiply(m4.yRotation(object.shadows.lightRotationY), lmat);
      // get the zAxis from the matrix
      // negate it because lookAt looks down the -Z axis
      object.shadows.lightDirection = [-lmat[8], -lmat[9], -lmat[10]];
      // object.shadows.lightDirection = [-0, -0, -1];
    }

    // test
    const viewMatrix = m4.inverse(lmat);
        // first draw from the POV of the light
        const lightWorldMatrix = m4.lookAt(
          [settings.posX, settings.posY, settings.posZ],          // position
          [settings.targetX, settings.targetY, settings.targetZ], // target
          [0, 1, 0],                                              // up
      );
      const lightProjectionMatrix = settings.perspective
          ? m4.perspective(
              degToRad(settings.fieldOfView),
              settings.projWidth / settings.projHeight,
              0.5,  // near
              10)   // far
          : m4.orthographic(
              -settings.projWidth / 2,   // left
               settings.projWidth / 2,   // right
              -settings.projHeight / 2,  // bottom
               settings.projHeight / 2,  // top
               0.5,                      // near
               10);                      // far

      // draw to the depth texture
      world.GL.gl.bindFramebuffer(world.GL.gl.FRAMEBUFFER,  object.shadows.depthFramebuffer);
      world.GL.gl.viewport(0, 0, 512, 512);
      world.GL.gl.clear( world.GL.gl.COLOR_BUFFER_BIT |  world.GL.gl.DEPTH_BUFFER_BIT);

      // draw 
      let textureMatrix = m4.identity();
      textureMatrix = m4.translate(textureMatrix, 0.5, 0.5, 0.5);
      textureMatrix = m4.scale(textureMatrix, 0.5, 0.5, 0.5);
      textureMatrix = m4.multiply(textureMatrix, lightProjectionMatrix);
      // use the inverse of this world matrix to make
      // a matrix that will transform other positions
      // to be relative this world space.
      textureMatrix = m4.multiply(
          textureMatrix,
          m4.inverse(lightWorldMatrix));

      world.GL.gl.uniform4fv(object.shaderProgram.u_textureMatrix, textureMatrix);

    world.GL.gl.uniform3fv(object.shaderProgram.lightDirectionLocation, object.shadows.lightDirection);
    world.GL.gl.uniform1f(object.shaderProgram.innerLimitLocation, Math.cos(object.shadows.innerLimit));
    world.GL.gl.uniform1f(object.shaderProgram.outerLimitLocation, Math.cos(object.shadows.outerLimit));

      // TEST 
      world.GL.gl.drawElements(world.GL.gl[object.glDrawElements.mode], object.glDrawElements.numberOfIndicesRender, world.GL.gl.UNSIGNED_SHORT, 0);

      world.GL.gl.bindFramebuffer(world.GL.gl.FRAMEBUFFER, null);
      world.GL.gl.viewport(0, 0, world.GL.gl.canvas.width, world.GL.gl.canvas.height);
      world.GL.gl.clearColor(1, 1, 1, 1);
      world.GL.gl.clear(world.GL.gl.COLOR_BUFFER_BIT | world.GL.gl.DEPTH_BUFFER_BIT);

      // REPEAT NORMAL TEX
      world.GL.gl.activeTexture(world.GL.gl['TEXTURE' + 0]);
      world.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.shadows.TEST);

      // world.GL.gl.pixelStorei(world.GL.gl.UNPACK_FLIP_Y_WEBGL, false);
      // world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MAG_FILTER, world.GL.gl.NEAREST);

      // world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MIN_FILTER, world.GL.gl.NEAREST);
      // world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_S, world.GL.gl.CLAMP_TO_EDGE);
      // world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_T, world.GL.gl.CLAMP_TO_EDGE);
      // world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, t);

  }

  world.GL.gl.drawElements(world.GL.gl[object.glDrawElements.mode], object.glDrawElements.numberOfIndicesRender, world.GL.gl.UNSIGNED_SHORT, 0);
  object.instancedDraws.overrideDrawArraysInstance(object);

  this.mvPopMatrix(object.mvMatrix, this.mvMatrixStack);
};

Error logs:

250x GL_INVALID_OPERATION: Feedback loop formed between Framebuffer and active Texture.

1x GL_INVALID_OPERATION: Feedback loop formed between Framebuffer and active Texture.

Shaders must be #version 300 es or i can keep it on ver 2 ?

Any suggestion ?


Solution

  • Feedback loop formed between Framebuffer and active Texture.

    You cannot render to a texture that is also used as a source in the fragment shader. This is a feedback loop. You will need 2 textures. One that you read from and one that you render into. Switch this to textures before each frame (ping-pong shading).