Search code examples
webgl2opengl-es-3.0matrix-engine

Change camera view for RENDERBUFFER but not for main render view


I got nice working RENDERBUFFER buffer using example but i cant change camera view only for framebuffer render view.

I wanna make second camera with own camera params...

Creating framebuffer:

function makeFbo() {
//////////////////////////////////////////////////////
  // TEST 2 Success for now just fbo
  // gl.getParameter(gl.MAX_DRAW_BUFFERS)
  //////////////////////////////////////////////////////
  var framebuffer, texture, depthBuffer;
  console.log('FBO MAKE FUNC !!!');

  var error = function() {
    console.log('Error in creating FBO!');
    return null;
  }

  framebuffer = gl.createFramebuffer();
  if(!framebuffer) {
    console.log('Failed to create frame buffer object');
    return error();
  }

  texture = gl.createTexture();
  if(!texture) {
    console.log('Failed to create texture object');
    return error();
  }

  // local
  var OFFSCREEN_WIDTH = 512;
  var OFFSCREEN_HEIGHT = 512;

  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  framebuffer.texture = texture;

  depthBuffer = gl.createRenderbuffer();
  if(!depthBuffer) {
    console.log('Failed to create renderbuffer object');
    return error();
  }
  gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
  gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT);

  // Attach the texture and the renderbuffer object to the FBO
  gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
  gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);

  // Check if FBO is configured correctly
  var e = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
  if(gl.FRAMEBUFFER_COMPLETE !== e) {
    console.log('Frame buffer object is incomplete: ' + e.toString());
    return error();
  }

  // Unbind the buffer object
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  gl.bindTexture(gl.TEXTURE_2D, null);
  gl.bindRenderbuffer(gl.RENDERBUFFER, null);

  return framebuffer;
}

Render func:

App.operation.reDrawGlobal = function(time) {
  modifyLooper(0);
  if(App.offScreenCanvas == false) reDrawID = requestAnimationFrame(App.operation.reDrawGlobal);
  world.renderPerspective();

  for(var t = 0;t < App.updateBeforeDraw.length;t++) {
    App.updateBeforeDraw[t].UPDATE();
  }


  // ....


  // reset to zero
  physicsLooper = 0;

  // Must be override for performance 
  // - non FBO and FBO option draw coroutine

  // hc 512
  if(world.FBOS.length > 0) world.GL.gl.bindFramebuffer(world.GL.gl.FRAMEBUFFER, world.FBOS[0].FB);

  world.GL.gl.viewport(0, 0, 512, 512);
  world.GL.gl.clearColor(0.2, 0.2, 0.4, 1.0);
  world.GL.gl.clear(world.GL.gl.COLOR_BUFFER_BIT | world.GL.gl.DEPTH_BUFFER_BIT);

  world.GL.gl.enable(world.GL.gl.DEPTH_TEST);
  world.GL.gl.disable(world.GL.gl.BLEND);
  world.GL.gl.depthMask(true);

  // big test !!
  if(typeof matrixEngine.Events.camera.xPosMemo === 'undefined') {
    matrixEngine.Events.camera.xPosMemo = matrixEngine.Events.camera.xPos;
    matrixEngine.Events.camera.zPosMemo = matrixEngine.Events.camera.zPos;
    matrixEngine.Events.camera.yPosMemo = matrixEngine.Events.camera.yPos;

    matrixEngine.Events.camera.xPos += 5;
    matrixEngine.Events.camera.zPos += 5;
    matrixEngine.Events.camera.yPos += 5;
  } else {
    //  bigtest !!  NO special success !
    // matrixEngine.Events.camera.xPos = matrixEngine.Events.camera.xPosMemo;
    // matrixEngine.Events.camera.zPos =matrixEngine.Events.camera.zPosMemo;
    // matrixEngine.Events.camera.yPos = matrixEngine.Events.camera.yPosMemo;
  }

  // - draw all `non fbo` and `no blend`
  while(looper <= world.contentList.length - 1) {
    if(world.contentList[looper].visible === true &&
      !world.contentList[looper].FBO &&
      world.contentList[looper].glBlend.blendEnabled == false) {
      if('triangle' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawTriangle(world.contentList[looper]);
        // world.animate(world.contentList[looper]);
      } else if('square' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawSquare(world.contentList[looper]);
        // world.animate(world.contentList[looper]);
      } else if('cube' == world.contentList[looper].type ||
        'cubeTex' == world.contentList[looper].type ||
        'cubeLightTex' == world.contentList[looper].type ||
        'cubeMap' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawCube(world.contentList[looper]);
        // world.animate(world.contentList[looper]);
      } else if('pyramid' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawPyramid(world.contentList[looper]);
        // world.animate(world.contentList[looper]);
      } else if('obj' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawObj(world.contentList[looper]);
        // world.animate(world.contentList[looper]);
      } else if('squareTex' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawSquareTex(world.contentList[looper]);
        // world.animate(world.contentList[looper]);
      } else if('sphereLightTex' == world.contentList[looper].type || 'sphere' == world.contentList[looper].type || 'generatorLightTex' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawSphere(world.contentList[looper]);
        // world.animate(world.contentList[looper]);
      }
    }
    modifyLooper(looper + 1);
  }

  modifyLooper(0);

  // maybe no need here
  world.GL.gl.enable(world.GL.gl.BLEND);
  world.GL.gl.depthMask(false);

  // all non FBO but blended
  while(looper <= world.contentList.length - 1) {
    if(world.contentList[looper].visible === true &&
      !world.contentList[looper].FBO &&
      world.contentList[looper].glBlend.blendEnabled == true) {
      if('triangle' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawTriangle(world.contentList[looper]);
        // world.animate(world.contentList[looper]);
      } else if('square' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawSquare(world.contentList[looper]);
        // world.animate(world.contentList[looper]);
      } else if('cube' == world.contentList[looper].type ||
        'cubeTex' == world.contentList[looper].type ||
        'cubeLightTex' == world.contentList[looper].type ||
        'cubeMap' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawCube(world.contentList[looper]);
        // world.animate(world.contentList[looper]);
      } else if('pyramid' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawPyramid(world.contentList[looper]);
        // world.animate(world.contentList[looper]);
      } else if('obj' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawObj(world.contentList[looper]);
        // world.animate(world.contentList[looper]);
      } else if('squareTex' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawSquareTex(world.contentList[looper]);
        // world.animate(world.contentList[looper]);
      } else if('sphereLightTex' == world.contentList[looper].type || 'sphere' == world.contentList[looper].type || 'generatorLightTex' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawSphere(world.contentList[looper]);
        // world.animate(world.contentList[looper]);
      }
    }
    modifyLooper(looper + 1);
  }

  modifyLooper(0);
  world.GL.gl.depthMask(true);

  // Back to drawing on the main color buffer!
  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(0.0, 0.0, 0.0, 1.0);
  world.GL.gl.clear(world.GL.gl.COLOR_BUFFER_BIT | world.GL.gl.DEPTH_BUFFER_BIT);

  // Draw again all
  world.GL.gl.enable(world.GL.gl.DEPTH_TEST);
  world.GL.gl.disable(world.GL.gl.BLEND);
  world.GL.gl.depthMask(true);

  // all but no blend
  while(looper <= world.contentList.length - 1) {
    if(world.contentList[looper].visible === true &&
      world.contentList[looper].glBlend.blendEnabled == false) {
      if('triangle' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawTriangle(world.contentList[looper]);
        world.animate(world.contentList[looper]);
      } else if('square' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawSquare(world.contentList[looper]);
        world.animate(world.contentList[looper]);
      } else if('cube' == world.contentList[looper].type ||
        'cubeTex' == world.contentList[looper].type ||
        'cubeLightTex' == world.contentList[looper].type ||
        'cubeMap' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawCube(world.contentList[looper]);
        world.animate(world.contentList[looper]);
      } else if('pyramid' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawPyramid(world.contentList[looper]);
        world.animate(world.contentList[looper]);
      } else if('obj' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawObj(world.contentList[looper]);
        world.animate(world.contentList[looper]);
      } else if('squareTex' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawSquareTex(world.contentList[looper]);
        world.animate(world.contentList[looper]);
      } else if('sphereLightTex' == world.contentList[looper].type || 'sphere' == world.contentList[looper].type || 'generatorLightTex' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawSphere(world.contentList[looper]);
        world.animate(world.contentList[looper]);
      }
    }
    modifyLooper(looper + 1);
  }

  world.GL.gl.enable(world.GL.gl.BLEND);
  world.GL.gl.depthMask(false);
  modifyLooper(0);

  // all but blend
  while(looper <= world.contentList.length - 1) {
    if(world.contentList[looper].visible === true &&
      world.contentList[looper].glBlend.blendEnabled == true) {
      if('triangle' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawTriangle(world.contentList[looper]);
        world.animate(world.contentList[looper]);
      } else if('square' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawSquare(world.contentList[looper]);
        world.animate(world.contentList[looper]);
      } else if('cube' == world.contentList[looper].type ||
        'cubeTex' == world.contentList[looper].type ||
        'cubeLightTex' == world.contentList[looper].type ||
        'cubeMap' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawCube(world.contentList[looper]);
        world.animate(world.contentList[looper]);
      } else if('pyramid' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawPyramid(world.contentList[looper]);
        world.animate(world.contentList[looper]);
      } else if('obj' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawObj(world.contentList[looper]);
        world.animate(world.contentList[looper]);
      } else if('squareTex' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawSquareTex(world.contentList[looper]);
        world.animate(world.contentList[looper]);
      } else if('sphereLightTex' == world.contentList[looper].type || 'sphere' == world.contentList[looper].type || 'generatorLightTex' == world.contentList[looper].type) {
        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
        world.drawSphere(world.contentList[looper]);
        world.animate(world.contentList[looper]);
      }
    }
    modifyLooper(looper + 1);
  }

  modifyLooper(0);
  world.GL.gl.depthMask(true);

  if(App.raycast) {
    if(secondPass <= 2) {
      raycaster.touchCoordinate.enabled = false;
      secondPass = 0;
    }
  }

  secondPass++;
  physicsLooper = 0;
  updateFPS(1);

  if(App.offScreenCanvas == true) reDrawID = setTimeout(() => App.operation.reDrawGlobal(), App.redrawInterval);

  if(world.animLine) {
    // animatinLine
    world.globalAnimCounter++;
    if(world.globalAnimCounter >= world.globalAnimSequenceSize) {
      world.globalAnimCounter = 0;
      world.globalAnimCurSequence++;
      document.getElementById('globalAnimCurSequence').innerText = world.globalAnimCurSequence;
    }

    document.getElementById('globalAnimCounter').innerText = world.globalAnimCounter;
    document.getElementById('timeline').value = world.globalAnimCounter;
  }


};

Here is example what i want. This is scene with +3 camera view with different view.

Maybe i need to setup for every framebuffer special draw then then redraw all. I have feeling i will stack with blinking screen...

Any suggestion ?

Source enter image description here


Solution

  • I get framebuffer view only camera manipulate option when i put camera manipulation code before calling bindFramebuffer !

    • // reset camera come before redraw all !
    App.operation.reDrawGlobal = function(time) {
      modifyLooper(0);
      if(App.offScreenCanvas == false) reDrawID = requestAnimationFrame(App.operation.reDrawGlobal);
      world.renderPerspective();
    
      for(var t = 0;t < App.updateBeforeDraw.length;t++) {
        App.updateBeforeDraw[t].UPDATE();
      }
    
    
      // ....
    
    
      // reset to zero
      physicsLooper = 0;
    
      // Must be override for performance 
      // - non FBO and FBO option draw coroutine
    
      // hc 512
      if(world.FBOS.length > 0) {
    
      // camera manipulation code must be before bindFramebuffer !!!
      if(typeof matrixEngine.Events.camera.xPosMemo === 'undefined') {
        matrixEngine.Events.camera.xPosMemo = matrixEngine.Events.camera.xPos;
        matrixEngine.Events.camera.zPosMemo = matrixEngine.Events.camera.zPos;
        matrixEngine.Events.camera.yPosMemo = matrixEngine.Events.camera.yPos;
    
        matrixEngine.Events.camera.xPos += 5;
        matrixEngine.Events.camera.zPos += 5;
        matrixEngine.Events.camera.yPos += 5; // ......
      } 
    
    
    world.GL.gl.bindFramebuffer(world.GL.gl.FRAMEBUFFER, world.FBOS[0].FB);
    
    }
    
      world.GL.gl.viewport(0, 0, 512, 512);
      world.GL.gl.clearColor(0.2, 0.2, 0.4, 1.0);
      world.GL.gl.clear(world.GL.gl.COLOR_BUFFER_BIT | world.GL.gl.DEPTH_BUFFER_BIT);
    
      world.GL.gl.enable(world.GL.gl.DEPTH_TEST);
      world.GL.gl.disable(world.GL.gl.BLEND);
      world.GL.gl.depthMask(true);
    
    
      // - draw all `non fbo` and `no blend`
      while(looper <= world.contentList.length - 1) {
        if(world.contentList[looper].visible === true &&
          !world.contentList[looper].FBO &&
          world.contentList[looper].glBlend.blendEnabled == false) {
          if('triangle' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawTriangle(world.contentList[looper]);
            // world.animate(world.contentList[looper]);
          } else if('square' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawSquare(world.contentList[looper]);
            // world.animate(world.contentList[looper]);
          } else if('cube' == world.contentList[looper].type ||
            'cubeTex' == world.contentList[looper].type ||
            'cubeLightTex' == world.contentList[looper].type ||
            'cubeMap' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawCube(world.contentList[looper]);
            // world.animate(world.contentList[looper]);
          } else if('pyramid' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawPyramid(world.contentList[looper]);
            // world.animate(world.contentList[looper]);
          } else if('obj' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawObj(world.contentList[looper]);
            // world.animate(world.contentList[looper]);
          } else if('squareTex' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawSquareTex(world.contentList[looper]);
            // world.animate(world.contentList[looper]);
          } else if('sphereLightTex' == world.contentList[looper].type || 'sphere' == world.contentList[looper].type || 'generatorLightTex' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawSphere(world.contentList[looper]);
            // world.animate(world.contentList[looper]);
          }
        }
        modifyLooper(looper + 1);
      }
    
      modifyLooper(0);
    
      // maybe no need here
      world.GL.gl.enable(world.GL.gl.BLEND);
      world.GL.gl.depthMask(false);
    
      // all non FBO but blended
      while(looper <= world.contentList.length - 1) {
        if(world.contentList[looper].visible === true &&
          !world.contentList[looper].FBO &&
          world.contentList[looper].glBlend.blendEnabled == true) {
          if('triangle' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawTriangle(world.contentList[looper]);
            // world.animate(world.contentList[looper]);
          } else if('square' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawSquare(world.contentList[looper]);
            // world.animate(world.contentList[looper]);
          } else if('cube' == world.contentList[looper].type ||
            'cubeTex' == world.contentList[looper].type ||
            'cubeLightTex' == world.contentList[looper].type ||
            'cubeMap' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawCube(world.contentList[looper]);
            // world.animate(world.contentList[looper]);
          } else if('pyramid' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawPyramid(world.contentList[looper]);
            // world.animate(world.contentList[looper]);
          } else if('obj' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawObj(world.contentList[looper]);
            // world.animate(world.contentList[looper]);
          } else if('squareTex' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawSquareTex(world.contentList[looper]);
            // world.animate(world.contentList[looper]);
          } else if('sphereLightTex' == world.contentList[looper].type || 'sphere' == world.contentList[looper].type || 'generatorLightTex' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawSphere(world.contentList[looper]);
            // world.animate(world.contentList[looper]);
          }
        }
        modifyLooper(looper + 1);
      }
    
      modifyLooper(0);
      world.GL.gl.depthMask(true);
    
      // Back to drawing on the main color buffer!
      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(0.0, 0.0, 0.0, 1.0);
      world.GL.gl.clear(world.GL.gl.COLOR_BUFFER_BIT | world.GL.gl.DEPTH_BUFFER_BIT);
    
      // Draw again all
      world.GL.gl.enable(world.GL.gl.DEPTH_TEST);
      world.GL.gl.disable(world.GL.gl.BLEND);
      world.GL.gl.depthMask(true);
    
      // reset camera
      if(typeof matrixEngine.Events.camera.zPosMemo !== 'undefined') {
        matrixEngine.Events.camera.zPos = matrixEngine.Events.camera.zPosMemo;
        matrixEngine.Events.camera.xPos = matrixEngine.Events.camera.xPosMemo;
        matrixEngine.Events.camera.yPos = matrixEngine.Events.camera.yPosMemo;
      }
    
      // all but no blend
      while(looper <= world.contentList.length - 1) {
        if(world.contentList[looper].visible === true &&
          world.contentList[looper].glBlend.blendEnabled == false) {
          if('triangle' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawTriangle(world.contentList[looper]);
            world.animate(world.contentList[looper]);
          } else if('square' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawSquare(world.contentList[looper]);
            world.animate(world.contentList[looper]);
          } else if('cube' == world.contentList[looper].type ||
            'cubeTex' == world.contentList[looper].type ||
            'cubeLightTex' == world.contentList[looper].type ||
            'cubeMap' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawCube(world.contentList[looper]);
            world.animate(world.contentList[looper]);
          } else if('pyramid' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawPyramid(world.contentList[looper]);
            world.animate(world.contentList[looper]);
          } else if('obj' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawObj(world.contentList[looper]);
            world.animate(world.contentList[looper]);
          } else if('squareTex' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawSquareTex(world.contentList[looper]);
            world.animate(world.contentList[looper]);
          } else if('sphereLightTex' == world.contentList[looper].type || 'sphere' == world.contentList[looper].type || 'generatorLightTex' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawSphere(world.contentList[looper]);
            world.animate(world.contentList[looper]);
          }
        }
        modifyLooper(looper + 1);
      }
    
      world.GL.gl.enable(world.GL.gl.BLEND);
      world.GL.gl.depthMask(false);
      modifyLooper(0);
    
      // all but blend
      while(looper <= world.contentList.length - 1) {
        if(world.contentList[looper].visible === true &&
          world.contentList[looper].glBlend.blendEnabled == true) {
          if('triangle' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawTriangle(world.contentList[looper]);
            world.animate(world.contentList[looper]);
          } else if('square' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawSquare(world.contentList[looper]);
            world.animate(world.contentList[looper]);
          } else if('cube' == world.contentList[looper].type ||
            'cubeTex' == world.contentList[looper].type ||
            'cubeLightTex' == world.contentList[looper].type ||
            'cubeMap' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawCube(world.contentList[looper]);
            world.animate(world.contentList[looper]);
          } else if('pyramid' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawPyramid(world.contentList[looper]);
            world.animate(world.contentList[looper]);
          } else if('obj' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawObj(world.contentList[looper]);
            world.animate(world.contentList[looper]);
          } else if('squareTex' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawSquareTex(world.contentList[looper]);
            world.animate(world.contentList[looper]);
          } else if('sphereLightTex' == world.contentList[looper].type || 'sphere' == world.contentList[looper].type || 'generatorLightTex' == world.contentList[looper].type) {
            world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
            world.drawSphere(world.contentList[looper]);
            world.animate(world.contentList[looper]);
          }
        }
        modifyLooper(looper + 1);
      }
    
      modifyLooper(0);
      world.GL.gl.depthMask(true);
    
      if(App.raycast) {
        if(secondPass <= 2) {
          raycaster.touchCoordinate.enabled = false;
          secondPass = 0;
        }
      }
    
      secondPass++;
      physicsLooper = 0;
      updateFPS(1);
    
    };