Day and Night Cycle Filter - UQdeco2800/2022-studio-1 GitHub Wiki

Page Navigation

Jump to a section or return to Day and Night Cycle Summary here!

Summary

The day and night cycle component or filter is in charge of rendering the shader effects that show the effects of dawn,day,dusk and night to the player.

It's called during the render cycle. Renderer.java makes sure to revert to default shader when rendering UI elements thus leaving UI elements unshaded.

Technical

UML

Astah - Fig. 1 - Green are the ones added by feature team

Design

It's coupled to InputComponent as we wanted to be able to toggle the VFX on or off depending on a key press. The key in question is the period key. When pressed it will toggle the effect on or off. This feature is useful for those that wish to inspect the visuals of their designs without the shader in the way.

Although not shown in the UML. The RenderService.java uses the class to apply the shader. Internally the class sets the correct shade colour and the intensity corresponding with that part of the day which it receives through the event handler. The justification for coupling it with RenderService is due to the fact that that's where rendering takes place and it seems like the right place to apply the shader. Furthermore, in the future the render service could be used to hold different sprite batches for different renderables and use those batches instead to avoid shading.

Implementation

DayNightCycleComponent is used inside RenderService it's applied to the batch only for none UI elements as shown below:

  public void render(SpriteBatch batch) {
    for (Array<Renderable> layer : renderables) {
      // Sort into rendering order
      layer.sort();

      for (Renderable renderable : layer) {
        if (dayNightCycleComponent != null) {
          if (AtlantisSinks.gameRunning) {
            dayNightCycleComponent.render(batch);
          }
        }
        renderable.render(batch);
      }
    }
  }

Shading was achieved through 2 OPenGL Shader Language files. One file known as base.vert chooses which parts of the pixels to be shaded while the fragmentation bit sits on top of it. These files are then compiled by ligGDX ShaderProgram and then applied to sprite batches.

./core/assets/shaders
├── base.vert
└── light.frag
        ShaderProgram.pedantic = false;
        var vertexShader = Gdx.files.internal("shaders/base.vert");
        var lightShader=  Gdx.files.internal("shaders/light.frag");
        this.dayNightCycleShader = new ShaderProgram(vertexShader, lightShader); // --> ready to use shader

For more technical details about implementation please see the JavaDoc.

Challenges

One of the challenges faced while coming up with this component was how to get other UI elements not to be shaded. For instance the terrain (map) was not correctly shaded - or to be more precise, not shaded at all. Several hours of debugging revealed that TiledMapRenderer used in TerrainComponent.java, used it's own internal sprite batch. So to overcome this, the internal sprite batch was modified to use the custom shader:

  if (renderer != null) {
      try {
        this.batchedMapTileSpriteBatch = (SpriteBatch) ((BatchTiledMapRenderer) renderer).getBatch();
      } catch(ClassCastException e) {
        // issue caused when being mocked
        this.batchedMapTileSpriteBatch = null;
      }

Then the shader was modified in draw()

  @Override
  public void draw(SpriteBatch batch) {
    tiledMapRenderer.setView(camera);
    // render night affect (using tiledmapRenderer batch)
    if (dayNightCycleComponent != null && batchedMapTileSpriteBatch != null) {
      dayNightCycleComponent.render(batchedMapTileSpriteBatch);
    }
    tiledMapRenderer.render();
  }

What was learned from this challenge was useful. It showed that if you didn't want the shader applied to some elements you can use a different sprite batch that hasn't got the shader set - or in other words, that uses the default shader.

Testing

Day and Night Cycle Filter Demonstration


Final Sprint (Sprint 4) Polishing

Fading Effect

Updated UML

To improve the game's overral experience we decided to let the different parts of day slowly fade into each other for a seamless experience. The abrupt change can catch users by surprise and so the gradual phase reminds users that it's about to be night or day.

To make this possible DayNigtCycleComponent was modified with the addition of a few new methods, highlighted in blue in the above class diagram. A method was added to return the amount of the gradual fade would have to progress. The fade is then stepped through based on the difference between it and the target. It can either get darker or lighter. The fade step only occurs for a set interval of milliseconds which are configurable in the class. So for instance we can make a fade step every 500ms and so on.

Back to Day and Night Cycle Summary

⚠️ **GitHub.com Fallback** ⚠️