// TODO: have a flag to invert the eyes (Cross Eye 3D), as mentioned in
  // TODO: http://forum.terasology.org/threads/happy-coding.1018/#post-11264
  private void renderFinalStereoImage(WorldRenderer.WorldRenderingStage renderingStage) {
    if (renderingProcess.isNotTakingScreenshot()) {
      buffers.sceneFinal.bind();
    } else {
      buffers.ocUndistorted.bind();
    }

    switch (renderingStage) {
      case LEFT_EYE:
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        renderFullscreenQuad(0, 0, fullScale.width() / 2, fullScale.height());

        break;

      case RIGHT_EYE:
        // no glClear() here: the rendering for the second eye is being added besides the first
        // eye's rendering
        renderFullscreenQuad(
            fullScale.width() / 2 + 1, 0, fullScale.width() / 2, fullScale.height());

        if (renderingProcess.isNotTakingScreenshot()) {
          graphicState.bindDisplay();
          applyOculusDistortion(buffers.sceneFinal);

        } else {
          buffers.sceneFinal.bind();
          applyOculusDistortion(buffers.ocUndistorted);
          renderingProcess.saveScreenshot();
          // when saving a screenshot we do NOT send the image to screen,
          // to avoid the brief flicker of the screenshot for one frame
        }

        break;
    }
  }
  private void renderFinalMonoImage() {

    if (renderingProcess.isNotTakingScreenshot()) {
      graphicState.bindDisplay();
      renderFullscreenQuad(0, 0, Display.getWidth(), Display.getHeight());

    } else {
      buffers.sceneFinal.bind();

      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      renderFullscreenQuad(0, 0, fullScale.width(), fullScale.height());

      renderingProcess.saveScreenshot();
      // when saving a screenshot we do not send the image to screen,
      // to avoid the brief one-frame flicker of the screenshot

      // This is needed to avoid the UI (which is not currently saved within the
      // screenshot) being rendered for one frame with buffers.sceneFinal size.
      setViewportToWholeDisplay();
    }
  }
  private void updateOcShaderParametersForVP(
      int vpX,
      int vpY,
      int vpWidth,
      int vpHeight,
      WorldRenderer.WorldRenderingStage renderingStage) {
    float w = (float) vpWidth / fullScale.width();
    float h = (float) vpHeight / fullScale.height();
    float x = (float) vpX / fullScale.width();
    float y = (float) vpY / fullScale.height();

    float as = (float) vpWidth / vpHeight;

    materials.ocDistortion.setFloat4(
        "ocHmdWarpParam",
        OculusVrHelper.getDistortionParams()[0],
        OculusVrHelper.getDistortionParams()[1],
        OculusVrHelper.getDistortionParams()[2],
        OculusVrHelper.getDistortionParams()[3],
        true);

    float ocLensCenter =
        (renderingStage == WorldRenderer.WorldRenderingStage.RIGHT_EYE)
            ? -1.0f * OculusVrHelper.getLensViewportShift()
            : OculusVrHelper.getLensViewportShift();

    materials.ocDistortion.setFloat2(
        "ocLensCenter", x + (w + ocLensCenter * 0.5f) * 0.5f, y + h * 0.5f, true);
    materials.ocDistortion.setFloat2("ocScreenCenter", x + w * 0.5f, y + h * 0.5f, true);

    float scaleFactor = 1.0f / OculusVrHelper.getScaleFactor();

    materials.ocDistortion.setFloat2(
        "ocScale", (w / 2) * scaleFactor, (h / 2) * scaleFactor * as, true);
    materials.ocDistortion.setFloat2("ocScaleIn", (2 / w), (2 / h) / as, true);
  }
 private void setViewportTo(FBO.Dimensions dimensions) {
   glViewport(0, 0, dimensions.width(), dimensions.height());
 }
 private void setViewportToWholeDisplay() {
   glViewport(0, 0, fullScale.width(), fullScale.height());
 }
  private void applyOculusDistortion(FBO inputBuffer) {
    materials.ocDistortion.enable();

    int texId = 0;
    GL13.glActiveTexture(GL13.GL_TEXTURE0 + texId);
    inputBuffer.bindTexture();
    materials.ocDistortion.setInt("texInputBuffer", texId, true);

    if (renderingProcess.isNotTakingScreenshot()) {
      updateOcShaderParametersForVP(
          0,
          0,
          fullScale.width() / 2,
          fullScale.height(),
          WorldRenderer.WorldRenderingStage.LEFT_EYE);
      renderFullscreenQuad(0, 0, Display.getWidth(), Display.getHeight());
      updateOcShaderParametersForVP(
          fullScale.width() / 2 + 1,
          0,
          fullScale.width() / 2,
          fullScale.height(),
          WorldRenderer.WorldRenderingStage.RIGHT_EYE);
      renderFullscreenQuad(0, 0, Display.getWidth(), Display.getHeight());

    } else {
      // what follows -should- work also when there is no screenshot being taken, but somehow it
      // doesn't, hence the block above
      updateOcShaderParametersForVP(
          0,
          0,
          fullScale.width() / 2,
          fullScale.height(),
          WorldRenderer.WorldRenderingStage.LEFT_EYE);
      renderFullscreenQuad(0, 0, fullScale.width(), fullScale.height());
      updateOcShaderParametersForVP(
          fullScale.width() / 2 + 1,
          0,
          fullScale.width() / 2,
          fullScale.height(),
          WorldRenderer.WorldRenderingStage.RIGHT_EYE);
      renderFullscreenQuad(0, 0, fullScale.width(), fullScale.height());
    }
  }