Skip to content

Commit

Permalink
Merge pull request #1645 from heinezen/feature/multi-terrain-mesh
Browse files Browse the repository at this point in the history
Layer support in renderer
  • Loading branch information
TheJJ authored May 23, 2024
2 parents 36e3907 + 52663d6 commit 1904244
Show file tree
Hide file tree
Showing 50 changed files with 1,116 additions and 489 deletions.
Binary file added assets/test/textures/test_terrain2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions assets/test/textures/test_terrain2.terrain
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright 2023-2023 the openage authors. See copying.md for legal info.
# openage terrain definition file

version 2

texture 0 "test_terrain2.texture"

scalefactor 1.0

layer 0

frame 0 0 0 0
12 changes: 12 additions & 0 deletions assets/test/textures/test_terrain2.texture
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright 2023-2023 the openage authors.
# openage texture definition file

version 1

imagefile "test_terrain2.png"

size 500 500

pxformat rgba8 cbits=True

subtex 0 0 500 500 0 0
74 changes: 70 additions & 4 deletions doc/code/renderer/level1.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ Low-level renderer for communicating with the OpenGL and Vulkan APIs.

1. [Overview](#overview)
2. [Architecture](#architecture)
3. [Basic Usage](#basic--usage)
3. [Basic Usage](#basic-usage)
1. [Window/Renderer Creation](#windowrenderer-creation)
2. [Adding a Shader Program](#adding-a-shader-program)
3. [Creating a Renderable](#creating-a-renderable)
4. [Rendering and Displaying the Result](#rendering-and-displaying-the-result)
4. [Advanced Usage](#advanced-usage)
1. [Addressing Uniforms via numeric IDs](#addressing-uniforms-via-numeric-ids)
2. [Framebuffers / Multiple Render Passes](#framebuffers--multiple-render-passes)
3. [Complex Geometry](#complex-geometry)
4. [Uniform Buffers](#uniform-buffers)
3. [Defining Layers in a Render Pass](#defining-layers-in-a-render-pass)
4. [Complex Geometry](#complex-geometry)
5. [Uniform Buffers](#uniform-buffers)
5. [Thread-safety](#thread-safety)


Expand Down Expand Up @@ -44,7 +45,7 @@ The `resources` namespace provides classes for initializing and loading meshes,
These classes are independent from the specific OpenGL/Vulkan backends and can thus be passed to the
abstract interface of the renderer renderer to make them usable with graphics hardware.

## Basic Usage
## Basic Usage

Code examples can be found in the [renderer demos](/libopenage/renderer/demo/).
See the [testing docs](/doc/code/testing.md#python-demos) on how to try them out.
Expand Down Expand Up @@ -200,9 +201,11 @@ Finally, we can execute the rendering pipeline for all objects in the render pas
renderer->render(pass);
```
<!-- TODO: We have deactivated this behaviour for now
Before rendering, the render pass optimizes the order in which renderables are rendered to
minimize state changes on the GPU and save computation time. For example, the render pass
sorts the renderables by shader program, since changing them is an expensive operation.
-->
After rendering is finished, the window has to be updated to display the rendered result.
Expand Down Expand Up @@ -312,6 +315,69 @@ Renderable obj {
obj.depth_test = true;
```


### Defining Layers in a Render Pass

Layers give more fine-grained control over the draw order of renderables in a render pass. Every
layer has a priority that determines when associated renderables are drawn. Lower priority
renderables are drawn earlier, higher priority renderables are drawn later.

In comparison to using multiple render passes, layers do not require the (expensive) switching
of framebuffers between passes. The tradeoff is a slight overhead when inserting new renderables
into the render pass.

To assign renderables to a layer, we have to specify the priority in the `RenderPass::add_renderables(..)`
function call.

```c++
Renderable obj {
input,
geom
};
pass->add_renderables({ obj }, 42);
```
For existing layers, new renderables are always appended to the end of the layer. Renderables
are sorted into the correct position automatically when they are added:
```c++
pass->add_renderables({ obj1, obj2, obj3 }, 42);
pass->add_renderables({ obj4 }, 0);
pass->add_renderables({ obj5, obj6 }, 1337);
pass->add_renderables({ obj7 }, 0);
// draw order: obj4, obj7, obj1, obj2, obj3, obj5, obj6
// layers: prio 0 | prio 42 | prio 1337
```

When no priority is specified when calling `RenderPass::add_renderables(..)`, the highest
priority is assumed (which is `std::numeric_limits<int64_t>::max()`). Therefore,
objects added like this are always drawn last. It also means that these two calls are equal:

```c++
pass->add_renderables({ obj });
pass->add_renderables({ obj }, std::numeric_limits<int64_t>::max());
```
Layers are created lazily during insertion if no layer with the specified priority exists yet.
We can also create layers explicitly for a specific priority:
```c++
pass->add_layer(42);
```

When executing the rendering pipeline for a specific pass, renderables are drawn layer by layer.
By default, the renderer clears the depth buffer when switching to a new layer. This is done
under the assumption that layers with higher priority should always draw over layers with lower
priority, even when depth tests are active. This behavior can be deactivated when explicitly
creating a layer:

```c++
// keep depth testing
pass->add_layer(42, false);
```
### Complex Geometry
For displaying complex geometry like 3D objects or non-rectangular surfaces, the renderer
Expand Down
24 changes: 2 additions & 22 deletions libopenage/gamestate/terrain_chunk.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018-2023 the openage authors. See copying.md for legal info.
// Copyright 2018-2024 the openage authors. See copying.md for legal info.

#include "terrain_chunk.h"

Expand All @@ -22,22 +22,6 @@ void TerrainChunk::set_render_entity(const std::shared_ptr<renderer::terrain::Te
this->render_entity = entity;
}

void TerrainChunk::render_update(const time::time_t &time,
const std::string &terrain_path) {
if (this->render_entity != nullptr) {
// TODO: Update individual tiles instead of the whole chunk
std::vector<std::pair<terrain_elevation_t, std::string>> tiles;
tiles.reserve(this->tiles.size());
for (const auto &tile : this->tiles) {
tiles.emplace_back(tile.elevation, terrain_path);
}

this->render_entity->update(this->size,
tiles,
time);
}
}

const util::Vector2s &TerrainChunk::get_size() const {
return this->size;
}
Expand All @@ -46,17 +30,13 @@ const coord::tile_delta &TerrainChunk::get_offset() const {
return this->offset;
}

void TerrainChunk::set_terrain_path(const std::string &terrain_path) {
this->terrain_path = terrain_path;
}

void TerrainChunk::render_update(const time::time_t &time) {
if (this->render_entity != nullptr) {
// TODO: Update individual tiles instead of the whole chunk
std::vector<std::pair<terrain_elevation_t, std::string>> tiles;
tiles.reserve(this->tiles.size());
for (const auto &tile : this->tiles) {
tiles.emplace_back(tile.elevation, terrain_path);
tiles.emplace_back(tile.elevation, tile.terrain_asset_path);
}

this->render_entity->update(this->size,
Expand Down
29 changes: 8 additions & 21 deletions libopenage/gamestate/terrain_chunk.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,6 @@ class TerrainChunk {
*/
void set_render_entity(const std::shared_ptr<renderer::terrain::TerrainRenderEntity> &entity);

/**
* Update the render entity.
*
* @param time Simulation time of the update.
* @param terrain_path Path to the terrain definition used at \p time.
*/
void render_update(const time::time_t &time,
const std::string &terrain_path);

/**
* Get the size of this terrain chunk.
*
Expand All @@ -57,14 +48,11 @@ class TerrainChunk {
*/
const coord::tile_delta &get_offset() const;

// TODO: Remove test texture references

// Set the terrain path of this terrain chunk.
// TODO: Remove later
void set_terrain_path(const std::string &terrain_path);

// Send the current texture to the renderer.
// TODO: Replace later with render_update(time, terrain_path)
/**
* Update the render entity.
*
* @param time Simulation time of the update.
*/
void render_update(const time::time_t &time);

private:
Expand All @@ -81,17 +69,16 @@ class TerrainChunk {
coord::tile_delta offset;

/**
* Height map of the terrain chunk.
* Terrain tile info of the terrain chunk.
*
* Layout is row-major.
*/
std::vector<TerrainTile> tiles;

/**
* Render entity for pushing updates to the renderer. Can be \p nullptr.
*/
std::shared_ptr<renderer::terrain::TerrainRenderEntity> render_entity;

// TODO: Remove test texture references
std::string terrain_path;
};

} // namespace openage::gamestate
Loading

0 comments on commit 1904244

Please sign in to comment.