示例#1
0
  private void downsampleSceneInto1x1pixelsBuffer() {
    PerformanceMonitor.startActivity("Rendering eye adaption");

    materials.downSampler.enable();
    FBO downSampledFBO;

    for (int i = 4; i >= 0; i--) {

      downSampledFBO = buffers.downSampledScene[i];
      materials.downSampler.setFloat("size", downSampledFBO.width(), true);

      downSampledFBO.bind();

      setViewportTo(downSampledFBO.dimensions());
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      // TODO: move this block above, for consistency
      if (i == 4) {
        buffers.initialPost.bindTexture();
      } else {
        buffers.downSampledScene[i + 1].bindTexture();
      }

      renderFullscreenQuad();

      graphicState.bindDisplay(); // TODO: probably can be removed or moved out of the loop
    }

    setViewportToWholeDisplay(); // TODO: verify this is necessary

    PerformanceMonitor.endActivity();
  }
 private void checkForUnload() {
   PerformanceMonitor.startActivity("Unloading irrelevant chunks");
   int unloaded = 0;
   logger.debug("Compacting cache");
   Iterator<Vector3i> iterator = nearCache.keySet().iterator();
   while (iterator.hasNext()) {
     Vector3i pos = iterator.next();
     boolean keep = false;
     for (ChunkRelevanceRegion region : regions.values()) {
       if (region.getCurrentRegion().expand(UNLOAD_LEEWAY).encompasses(pos)) {
         keep = true;
         break;
       }
     }
     if (!keep) {
       // TODO: need some way to not dispose chunks being edited or processed (or do so safely)
       // Note: Above won't matter if all changes are on the main thread
       if (unloadChunkInternal(pos)) {
         iterator.remove();
         if (++unloaded >= UNLOAD_PER_FRAME) {
           break;
         }
       }
     }
   }
   PerformanceMonitor.endActivity();
 }
示例#3
0
 /**
  * If blur is enabled through the rendering settings, this method generates the images used by the
  * Blur effect when underwater and for the Depth of Field effect when above water.
  *
  * <p>For more information on blur: http://en.wikipedia.org/wiki/Defocus_aberration For more
  * information on DoF: http://en.wikipedia.org/wiki/Depth_of_field
  */
 public void generateBlurPasses() {
   if (renderingConfig.getBlurIntensity() != 0) {
     PerformanceMonitor.startActivity("Generating Blur Passes");
     generateBlur(buffers.sceneBlur0);
     generateBlur(buffers.sceneBlur1);
     PerformanceMonitor.endActivity();
   }
 }
示例#4
0
  // TODO: verify if this can be achieved entirely in the GPU, during tone mapping perhaps?
  public void downsampleSceneAndUpdateExposure() {
    if (renderingConfig.isEyeAdaptation()) {
      PerformanceMonitor.startActivity("Updating exposure");

      downsampleSceneInto1x1pixelsBuffer();

      renderingProcess
          .getCurrentReadbackPBO()
          .copyFromFBO(
              buffers.downSampledScene[0].fboId, 1, 1, GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE);

      renderingProcess.swapReadbackPBOs();

      ByteBuffer pixels = renderingProcess.getCurrentReadbackPBO().readBackPixels();

      if (pixels.limit() < 3) {
        logger.error("Failed to auto-update the exposure value.");
        return;
      }

      // TODO: make this line more readable by breaking it in smaller pieces
      currentSceneLuminance =
          0.2126f * (pixels.get(2) & 0xFF) / 255.f
              + 0.7152f * (pixels.get(1) & 0xFF) / 255.f
              + 0.0722f * (pixels.get(0) & 0xFF) / 255.f;

      float targetExposure = hdrMaxExposure;

      if (currentSceneLuminance > 0) {
        targetExposure = hdrTargetLuminance / currentSceneLuminance;
      }

      float maxExposure = hdrMaxExposure;

      if (CoreRegistry.get(BackdropProvider.class).getDaylight()
          == 0.0) { // TODO: fetch the backdropProvider earlier and only once
        maxExposure = hdrMaxExposureNight;
      }

      if (targetExposure > maxExposure) {
        targetExposure = maxExposure;
      } else if (targetExposure < hdrMinExposure) {
        targetExposure = hdrMinExposure;
      }

      currentExposure = TeraMath.lerp(currentExposure, targetExposure, hdrExposureAdjustmentSpeed);

    } else {
      if (CoreRegistry.get(BackdropProvider.class).getDaylight() == 0.0) {
        currentExposure = hdrMaxExposureNight;
      } else {
        currentExposure = hdrExposureDefault;
      }
    }
    PerformanceMonitor.endActivity();
  }
 @Override
 public void update(float delta) {
   PerformanceMonitor.startActivity("Temp Blocks Cleanup");
   List<EntityRef> toRemove = Lists.newArrayList(temporaryBlockEntities);
   temporaryBlockEntities.clear();
   for (EntityRef entity : toRemove) {
     cleanUpTemporaryEntity(entity);
   }
   PerformanceMonitor.endActivity();
 }
示例#6
0
 /**
  * If bloom is enabled via the rendering settings, this method generates the images needed for the
  * bloom shader effect and stores them in their own frame buffers.
  *
  * <p>This effects renders adds fringes (or "feathers") of light to areas of intense brightness.
  * This in turn give the impression of those areas partially overwhelming the camera or the eye.
  *
  * <p>For more information see: http://en.wikipedia.org/wiki/Bloom_(shader_effect)
  */
 public void generateBloomPasses() {
   if (renderingConfig.isBloom()) {
     PerformanceMonitor.startActivity("Generating Bloom Passes");
     generateHighPass();
     generateBloom(buffers.sceneBloom0);
     generateBloom(buffers.sceneBloom1);
     generateBloom(buffers.sceneBloom2);
     PerformanceMonitor.endActivity();
   }
 }
示例#7
0
  /**
   * If each is enabled through the rendering settings, this method adds depth-of-field blur, motion
   * blur and film grain to the rendering obtained so far. If OculusVR support is enabled, it
   * composes (over two calls) the images for each eye into a single image, and applies a distortion
   * pattern to each, to match the optics in the OculusVR headset.
   *
   * <p>Finally, it either sends the image to the display or, when taking a screenshot, instructs
   * the rendering process to save it to a file. // TODO: update this sentence when the
   * FrameBuffersManager becomes available.
   *
   * @param renderingStage Can be MONO, LEFT_EYE or RIGHT_EYE, and communicates to the method
   *     weather it is dealing with a standard display or an OculusVR setup, and in the latter case,
   *     which eye is currently being rendered. Notice that if the OculusVR support is enabled, the
   *     image is sent to screen or saved to file only when the value passed in is RIGHT_EYE, as the
   *     processing for the LEFT_EYE comes first and leads to an incomplete image.
   */
  public void finalPostProcessing(WorldRenderer.WorldRenderingStage renderingStage) {
    PerformanceMonitor.startActivity("Rendering final scene");

    if (!renderingDebugConfig.isEnabled()) {
      materials.finalPost.enable();
    } else {
      materials.debug.enable();
    }

    if (!renderingConfig.isOculusVrSupport()) {
      renderFinalMonoImage();
    } else {
      renderFinalStereoImage(renderingStage);
    }

    PerformanceMonitor.endActivity();
  }
示例#8
0
  // TODO: Tone mapping usually maps colors from HDR to a more limited range,
  // TODO: i.e. the 24 bit a monitor can display. This method however maps from an HDR buffer
  // TODO: to another HDR buffer and this puzzles me. Will need to dig deep in the shader to
  // TODO: see what it does.
  public void generateToneMappedScene() {
    PerformanceMonitor.startActivity("Tone mapping");

    materials.toneMapping.enable();

    buffers.sceneToneMapped.bind();

    setViewportTo(buffers.sceneToneMapped.dimensions());
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // TODO: verify this is necessary

    renderFullscreenQuad();

    graphicState.bindDisplay(); // TODO: verify this is necessary
    setViewportToWholeDisplay(); // TODO: verify this is necessary

    PerformanceMonitor.endActivity();
  }
示例#9
0
  /**
   * Adds chromatic aberration, light shafts, 1/8th resolution bloom, vignette onto the rendering
   * achieved so far. Stores the result into its own buffer to be used at a later stage.
   */
  public void initialPostProcessing() {
    PerformanceMonitor.startActivity("Initial Post-Processing");
    materials.initialPost.enable();

    // TODO: verify what the inputs are
    buffers.initialPost.bind(); // TODO: see if we could write this straight into sceneOpaque

    setViewportTo(buffers.initialPost.dimensions());
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // TODO: verify this is necessary

    renderFullscreenQuad();

    graphicState.bindDisplay(); // TODO: verify this is necessary
    setViewportToWholeDisplay(); // TODO: verify this is necessary

    PerformanceMonitor.endActivity();
  }
示例#10
0
  /** Generates light shafts and stores them in their own FBO. */
  public void generateLightShafts() {
    if (renderingConfig.isLightShafts()) {
      PerformanceMonitor.startActivity("Rendering light shafts");

      materials.lightShafts.enable();
      // TODO: verify what the inputs are
      buffers.lightShafts.bind();

      setViewportTo(buffers.lightShafts.dimensions());
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // TODO: verify this is necessary

      renderFullscreenQuad();

      graphicState.bindDisplay(); // TODO: verify this is necessary
      setViewportToWholeDisplay(); // TODO: verify this is necessary

      PerformanceMonitor.endActivity();
    }
  }
  private void startSaving() {
    logger.info("Saving - Creating game snapshot");
    PerformanceMonitor.startActivity("Auto Saving");
    ComponentSystemManager componentSystemManager = CoreRegistry.get(ComponentSystemManager.class);
    for (ComponentSystem sys : componentSystemManager.iterateAll()) {
      sys.preSave();
    }

    saveRequested = false;
    saveTransaction = createSaveTransaction();
    saveThreadManager.offer(saveTransaction);

    for (ComponentSystem sys : componentSystemManager.iterateAll()) {
      sys.postSave();
    }
    scheduleNextAutoSave();
    PerformanceMonitor.endActivity();
    entitySetDeltaRecorder = new EntitySetDeltaRecorder(this.entityRefReplacingComponentLibrary);
    logger.info("Saving - Snapshot created: Writing phase starts");
  }
示例#12
0
 private void makeChunksAvailable() {
   List<ReadyChunkInfo> newReadyChunks = Lists.newArrayListWithExpectedSize(readyChunks.size());
   readyChunks.drainTo(newReadyChunks);
   for (ReadyChunkInfo readyChunkInfo : newReadyChunks) {
     nearCache.put(readyChunkInfo.getPos(), readyChunkInfo.getChunk());
     preparingChunks.remove(readyChunkInfo.getPos());
   }
   if (!newReadyChunks.isEmpty()) {
     sortedReadyChunks.addAll(newReadyChunks);
     Collections.sort(sortedReadyChunks, new ReadyChunkRelevanceComparator());
   }
   if (!sortedReadyChunks.isEmpty()) {
     boolean loaded = false;
     for (int i = sortedReadyChunks.size() - 1; i >= 0 && !loaded; i--) {
       ReadyChunkInfo chunkInfo = sortedReadyChunks.get(i);
       PerformanceMonitor.startActivity("Make Chunk Available");
       if (makeChunkAvailable(chunkInfo)) {
         sortedReadyChunks.remove(i);
         loaded = true;
       }
       PerformanceMonitor.endActivity();
     }
   }
 }
示例#13
0
  /**
   * The main loop runs until the EngineState is set back to INITIALIZED by shutdown() or until the
   * OS requests the application's window to be closed. Engine cleanup and disposal occur
   * afterwards.
   */
  private void mainLoop() {
    PerformanceMonitor.startActivity("Other");
    // MAIN GAME LOOP
    while (!shutdownRequested) {
      assetTypeManager.reloadChangedOnDisk();

      processPendingState();

      if (currentState == null) {
        shutdown();
        break;
      }

      Iterator<Float> updateCycles = timeSubsystem.getEngineTime().tick();

      for (EngineSubsystem subsystem : allSubsystems) {
        try (Activity ignored =
            PerformanceMonitor.startActivity(subsystem.getName() + " PreUpdate")) {
          subsystem.preUpdate(currentState, timeSubsystem.getEngineTime().getRealDelta());
        }
      }

      while (updateCycles.hasNext()) {
        float updateDelta = updateCycles.next(); // gameTime gets updated here!
        try (Activity ignored = PerformanceMonitor.startActivity("Main Update")) {
          currentState.update(updateDelta);
        }
      }

      // Waiting processes are set by modules via GameThread.a/synch() methods.
      GameThread.processWaitingProcesses();

      for (EngineSubsystem subsystem : getSubsystems()) {
        try (Activity ignored =
            PerformanceMonitor.startActivity(subsystem.getName() + " Subsystem postUpdate")) {
          subsystem.postUpdate(currentState, timeSubsystem.getEngineTime().getRealDelta());
        }
      }
      assetTypeManager.disposedUnusedAssets();

      PerformanceMonitor.rollCycle();
      PerformanceMonitor.startActivity("Other");
    }
    PerformanceMonitor.endActivity();
  }
示例#14
0
  @Override
  public void completeUpdate() {
    ReadyChunkInfo readyChunkInfo = lightMerger.completeMerge();
    if (readyChunkInfo != null) {
      Chunk chunk = readyChunkInfo.getChunk();
      chunk.lock();
      try {
        chunk.markReady();
        updateAdjacentChunksReadyFieldOf(chunk);
        updateAdjacentChunksReadyFieldOfAdjChunks(chunk);

        if (!readyChunkInfo.isNewChunk()) {
          PerformanceMonitor.startActivity("Generating Block Entities");
          generateBlockEntities(chunk);
          PerformanceMonitor.endActivity();
        }
        if (readyChunkInfo.getChunkStore() != null) {
          readyChunkInfo.getChunkStore().restoreEntities();
        }

        if (!readyChunkInfo.isNewChunk()) {
          PerformanceMonitor.startActivity("Sending OnAddedBlocks");
          readyChunkInfo
              .getBlockPositionMapppings()
              .forEachEntry(
                  new TShortObjectProcedure<TIntList>() {
                    @Override
                    public boolean execute(short id, TIntList positions) {
                      if (positions.size() > 0) {
                        blockManager
                            .getBlock(id)
                            .getEntity()
                            .send(new OnAddedBlocks(positions, registry));
                      }
                      return true;
                    }
                  });
          PerformanceMonitor.endActivity();
        }

        PerformanceMonitor.startActivity("Sending OnActivateBlocks");
        readyChunkInfo
            .getBlockPositionMapppings()
            .forEachEntry(
                new TShortObjectProcedure<TIntList>() {
                  @Override
                  public boolean execute(short id, TIntList positions) {
                    if (positions.size() > 0) {
                      blockManager
                          .getBlock(id)
                          .getEntity()
                          .send(new OnActivatedBlocks(positions, registry));
                    }
                    return true;
                  }
                });
        PerformanceMonitor.endActivity();

        if (!readyChunkInfo.isNewChunk()) {
          worldEntity.send(new OnChunkGenerated(readyChunkInfo.getPos()));
        }
        worldEntity.send(new OnChunkLoaded(readyChunkInfo.getPos()));
        for (ChunkRelevanceRegion region : regions.values()) {
          region.chunkReady(chunk);
        }
      } finally {
        chunk.unlock();
      }
    }
  }
示例#15
0
  /**
   * The main loop runs until the EngineState is set back to INITIALIZED by shutdown() or until the
   * OS requests the application's window to be closed. Engine cleanup and disposal occur
   * afterwards.
   */
  private void mainLoop() {
    NetworkSystem networkSystem = CoreRegistry.get(NetworkSystem.class);

    DisplayDevice display = CoreRegistry.get(DisplayDevice.class);

    PerformanceMonitor.startActivity("Other");
    // MAIN GAME LOOP
    while (engineState == EngineState.RUNNING && !display.isCloseRequested()) {

      long totalDelta;
      float updateDelta;
      float subsystemsDelta;

      // Only process rendering and updating once a second
      if (!display.isActive() && isHibernationAllowed()) {
        time.setPaused(true);
        Iterator<Float> updateCycles = time.tick();
        while (updateCycles.hasNext()) {
          updateCycles.next();
        }
        try {
          Thread.sleep(100);
        } catch (InterruptedException e) {
          logger.warn("Display inactivity sleep interrupted", e);
        }

        display.processMessages();
        time.setPaused(false);
        continue;
      }

      processPendingState();

      if (currentState == null) {
        shutdown();
        break;
      }

      Iterator<Float> updateCycles = time.tick();

      try (Activity ignored = PerformanceMonitor.startActivity("Network Update")) {
        networkSystem.update();
      }

      totalDelta = 0;
      while (updateCycles.hasNext()) {
        updateDelta = updateCycles.next(); // gameTime gets updated here!
        totalDelta += time.getDeltaInMs();
        try (Activity ignored = PerformanceMonitor.startActivity("Main Update")) {
          currentState.update(updateDelta);
        }
      }

      subsystemsDelta = totalDelta / 1000f;

      for (EngineSubsystem subsystem : getSubsystems()) {
        try (Activity ignored =
            PerformanceMonitor.startActivity(subsystem.getClass().getSimpleName())) {
          subsystem.preUpdate(currentState, subsystemsDelta);
        }
      }

      // Waiting processes are set by modules via GameThread.a/synch() methods.
      GameThread.processWaitingProcesses();

      for (EngineSubsystem subsystem : getSubsystems()) {
        try (Activity ignored =
            PerformanceMonitor.startActivity(subsystem.getClass().getSimpleName())) {
          subsystem.postUpdate(currentState, subsystemsDelta);
        }
      }

      PerformanceMonitor.rollCycle();
      PerformanceMonitor.startActivity("Other");
    }
    PerformanceMonitor.endActivity();

    // This becomes important only if display.isCloseRequested() is true.
    // In all other circumstances the EngineState is already set to
    // INITIALIZED by the time the flow gets here.
    engineState = EngineState.INITIALIZED;
  }