diff --git a/.github/workflows/Linux.yml b/.github/workflows/Linux.yml index 706ca34..f8d4935 100644 --- a/.github/workflows/Linux.yml +++ b/.github/workflows/Linux.yml @@ -18,7 +18,7 @@ jobs: - Release steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Pulling RaZ run: git submodule update --init --recursive @@ -62,16 +62,16 @@ jobs: # Additional dependencies are libc & libm (located in /usr/lib*), as well as libgcc_s & libstdc++ (which would require another package) - name: Packaging build run: | - mkdir Midgard-linux-${{ matrix.compiler.c }}-${{ matrix.build_type }}-${{ github.run_id }}/ && - cp -t Midgard-linux-${{ matrix.compiler.c }}-${{ matrix.build_type }}-${{ github.run_id }}/ \ + mkdir Midgard-linux-${{ matrix.compiler.c }}-${{ matrix.build_type }}-${{ github.sha }}/ && + cp -t Midgard-linux-${{ matrix.compiler.c }}-${{ matrix.build_type }}-${{ github.sha }}/ \ ${{ runner.workspace }}/build-${{ matrix.compiler.c }}/Midgard \ /usr/lib/*/libGL.so \ /usr/lib/*/libopenal.so - tar -cvf Midgard-linux-${{ matrix.compiler.c }}-${{ matrix.build_type }}-${{ github.run_id }}.tar \ - Midgard-linux-${{ matrix.compiler.c }}-${{ matrix.build_type }}-${{ github.run_id }}/ + tar -cvf Midgard-linux-${{ matrix.compiler.c }}-${{ matrix.build_type }}-${{ github.sha }}.tar \ + Midgard-linux-${{ matrix.compiler.c }}-${{ matrix.build_type }}-${{ github.sha }}/ - name: Upload build - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: Midgard-linux-${{ matrix.compiler.c }}-${{ matrix.build_type }}-${{ github.run_id }} - path: Midgard-linux-${{ matrix.compiler.c }}-${{ matrix.build_type }}-${{ github.run_id }}.tar + name: Midgard-linux-${{ matrix.compiler.c }}-${{ matrix.build_type }}-${{ github.sha }} + path: Midgard-linux-${{ matrix.compiler.c }}-${{ matrix.build_type }}-${{ github.sha }}.tar diff --git a/.github/workflows/Windows.yml b/.github/workflows/Windows.yml index 5dbc870..0a51176 100644 --- a/.github/workflows/Windows.yml +++ b/.github/workflows/Windows.yml @@ -17,7 +17,7 @@ jobs: - Release steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Pulling RaZ run: git submodule update --init --recursive @@ -53,8 +53,8 @@ jobs: rm C:/Midgard/lib -r - name: Upload build - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: Midgard-windows-${{ matrix.compiler.c }}-${{ matrix.build_type }}-${{ github.run_id }} + name: Midgard-windows-${{ matrix.compiler.c }}-${{ matrix.build_type }}-${{ github.sha }} path: | C:/Midgard diff --git a/CMakeLists.txt b/CMakeLists.txt index bdcee97..df88d96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -380,7 +380,7 @@ if (NOT MIDGARD_BUILD_RAZ) endif () target_link_directories(Midgard PRIVATE "${RAZ_LIB_DIR}") - target_include_directories(Midgard PUBLIC "${RAZ_ROOT}/include") + target_include_directories(Midgard SYSTEM PUBLIC "${RAZ_ROOT}/include") target_compile_definitions(Midgard PRIVATE RAZ_USE_WINDOW) # Raz::Window is needed # Additional linking flags @@ -434,6 +434,9 @@ else () # Use RaZ's compiler flags' script include("${RAZ_ROOT}/cmake/CompilerFlags.cmake") add_compiler_flags(Midgard PRIVATE) + + # Needed to use Tracy's GPU profiling + target_link_libraries(Midgard PRIVATE GLEW) else () message(FATAL_ERROR "Failed to find RaZ; the submodule must be downloaded") endif () diff --git a/README.md b/README.md index f81012d..20b0f8c 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ More progress screenshots are available on the wiki's [milestones page](https:// # Resources +- Wei et al. (2007) - [Fast Hydraulic Erosion Simulation and Visualization on GPU](https://inria.hal.science/inria-00402079/document) - Paris et al. (2020) - [Modeling Rocky Scenery using Implicit Blocks](https://hal.archives-ouvertes.fr/hal-02926218/file/2020-rocks-author.pdf) ([code](https://github.com/aparis69/Rock-fracturing)) - Paris et al. (2019) - [Desertscape Simulation](https://hal.archives-ouvertes.fr/hal-02273039/document) ([code](https://github.com/aparis69/Desertscapes-Simulation)) - Peytavie et al. (2019) - [Procedural Riverscapes](https://hal.archives-ouvertes.fr/hal-02281637/document) diff --git a/extern/RaZ b/extern/RaZ index 9cad0f6..d70a312 160000 --- a/extern/RaZ +++ b/extern/RaZ @@ -1 +1 @@ -Subproject commit 9cad0f68d1828108f43c47c4d4d399c82a6deb43 +Subproject commit d70a312742fcdfe08a12bf6d5ebae0417293a029 diff --git a/main.cpp b/main.cpp index dbff4ff..527cd3c 100644 --- a/main.cpp +++ b/main.cpp @@ -117,7 +117,7 @@ int main() { #if !defined(USE_OPENGL_ES) Raz::ImageFormat::save("colorMap.png", colorMap); Raz::ImageFormat::save("normalMap.png", normalMap); - Raz::ImageFormat::save("slopeMap.png", slopeMap); + Raz::ImageFormat::save("slopeMap.hdr", slopeMap); #endif ///////////////////// diff --git a/shaders/terrain_color.comp b/shaders/terrain_color.comp index 57de873..2a31e50 100644 --- a/shaders/terrain_color.comp +++ b/shaders/terrain_color.comp @@ -18,5 +18,10 @@ void main() { : (height < 0.66 ? mix(groundColor, rockColor, (height - 0.5) * 6.0) : mix(rockColor, snowColor, (height - 0.66) * 3.0)))); + // Applying gamma correction + // This shouldn't be needed here, as ideally the texture should be read later as sRGB; but as it's not possible to use imageRead/Store() on an sRGB texture, + // and to avoid duplicating them to use distinct ones for write & read operations, this correction is applied + color = pow(color, vec3(2.2)); + imageStore(uniColorMap, pixelCoords, vec4(color, 1.0)); } diff --git a/src/Midgard/DynamicTerrain.cpp b/src/Midgard/DynamicTerrain.cpp index 549bf5a..6faf14b 100644 --- a/src/Midgard/DynamicTerrain.cpp +++ b/src/Midgard/DynamicTerrain.cpp @@ -6,6 +6,10 @@ #include #include +#include +#include // Needed by TracyOpenGL.hpp +#include + namespace { constexpr int heightmapSize = 1024; @@ -40,6 +44,8 @@ inline void checkParameters(float& minTessLevel) { } // namespace DynamicTerrain::DynamicTerrain(Raz::Entity& entity) : Terrain(entity) { + ZoneScopedN("DynamicTerrain::DynamicTerrain"); + Raz::RenderShaderProgram& terrainProgram = m_entity.getComponent().getMaterials().front().getProgram(); terrainProgram.setTessellationControlShader(Raz::TessellationControlShader::loadFromSource(tessCtrlSource)); terrainProgram.setTessellationEvaluationShader(Raz::TessellationEvaluationShader::loadFromSource(tessEvalSource)); @@ -79,6 +85,8 @@ DynamicTerrain::DynamicTerrain(Raz::Entity& entity) : Terrain(entity) { DynamicTerrain::DynamicTerrain(Raz::Entity& entity, unsigned int width, unsigned int depth, float heightFactor, float flatness, float minTessLevel) : DynamicTerrain(entity) { + ZoneScopedN("DynamicTerrain::DynamicTerrain"); + Raz::RenderShaderProgram& terrainProgram = entity.getComponent().getMaterials().front().getProgram(); terrainProgram.setAttribute(Raz::Vec2u(width, depth), "uniTerrainSize"); terrainProgram.sendAttributes(); @@ -87,6 +95,8 @@ DynamicTerrain::DynamicTerrain(Raz::Entity& entity, unsigned int width, unsigned } void DynamicTerrain::setParameters(float minTessLevel, float heightFactor, float flatness) { + ZoneScopedN("DynamicTerrain::setParameters"); + Terrain::setParameters(heightFactor, flatness); ::checkParameters(minTessLevel); @@ -104,6 +114,8 @@ void DynamicTerrain::setParameters(float minTessLevel, float heightFactor, float } void DynamicTerrain::generate(unsigned int width, unsigned int depth, float heightFactor, float flatness, float minTessLevel) { + ZoneScopedN("DynamicTerrain::generate"); + auto& mesh = m_entity.getComponent(); mesh.getSubmeshes().resize(1); @@ -161,6 +173,9 @@ void DynamicTerrain::generate(unsigned int width, unsigned int depth, float heig } const Raz::Texture2D& DynamicTerrain::computeNoiseMap(float factor) { + ZoneScopedN("DynamicTerrain::computeNoiseMap"); + TracyGpuZone("DynamicTerrain::computeNoiseMap") + m_noiseProgram.setAttribute(factor, "uniNoiseFactor"); m_noiseProgram.sendAttributes(); m_noiseProgram.execute(heightmapSize, heightmapSize); @@ -169,12 +184,18 @@ const Raz::Texture2D& DynamicTerrain::computeNoiseMap(float factor) { } const Raz::Texture2D& DynamicTerrain::computeColorMap() { + ZoneScopedN("DynamicTerrain::computeColorMap"); + TracyGpuZone("DynamicTerrain::computeColorMap") + m_colorProgram.execute(heightmapSize, heightmapSize); return *m_colorMap; } const Raz::Texture2D& DynamicTerrain::computeSlopeMap() { + ZoneScopedN("DynamicTerrain::computeSlopeMap"); + TracyGpuZone("DynamicTerrain::computeSlopeMap") + m_slopeProgram.execute(heightmapSize, heightmapSize); return *m_slopeMap; diff --git a/src/Midgard/StaticTerrain.cpp b/src/Midgard/StaticTerrain.cpp index b9c3446..5df9c44 100644 --- a/src/Midgard/StaticTerrain.cpp +++ b/src/Midgard/StaticTerrain.cpp @@ -7,6 +7,8 @@ #include #include +#include + namespace { constexpr Raz::Vec3b waterColor(0, 0, 255); @@ -18,10 +20,14 @@ constexpr Raz::Vec3b snowColor(255, 255, 255); } // namespace StaticTerrain::StaticTerrain(Raz::Entity& entity, unsigned int width, unsigned int depth, float heightFactor, float flatness) : StaticTerrain(entity) { + ZoneScopedN("StaticTerrain::StaticTerrain"); + StaticTerrain::generate(width, depth, heightFactor, flatness); } void StaticTerrain::setParameters(float heightFactor, float flatness) { + ZoneScopedN("StaticTerrain::setParameters"); + checkParameters(heightFactor, flatness); remapVertices(heightFactor, flatness); @@ -32,6 +38,8 @@ void StaticTerrain::setParameters(float heightFactor, float flatness) { } void StaticTerrain::generate(unsigned int width, unsigned int depth, float heightFactor, float flatness) { + ZoneScopedN("StaticTerrain::generate"); + m_width = width; m_depth = depth; Terrain::setParameters(heightFactor, flatness); @@ -45,6 +53,8 @@ void StaticTerrain::generate(unsigned int width, unsigned int depth, float heigh vertices.resize(m_width * m_depth); Raz::Threading::parallelize(0, vertices.size(), [this, &vertices] (const Raz::Threading::IndexRange& range) noexcept { + ZoneScopedN("StaticTerrain::generate"); + for (std::size_t i = range.beginIndex; i < range.endIndex; ++i) { const auto xCoord = static_cast(i % m_width); const auto yCoord = static_cast(i / m_width); @@ -121,12 +131,16 @@ void StaticTerrain::generate(unsigned int width, unsigned int depth, float heigh } const Raz::Image& StaticTerrain::computeColorMap() { + ZoneScopedN("StaticTerrain::computeColorMap"); + m_colorMap = Raz::Image(m_width, m_depth, Raz::ImageColorspace::RGB); auto* imgData = static_cast(m_colorMap.getDataPtr()); const std::vector& vertices = m_entity.getComponent().getSubmeshes().front().getVertices(); Raz::Threading::parallelize(0, vertices.size(), [this, &vertices, imgData] (const Raz::Threading::IndexRange& range) noexcept { + ZoneScopedN("StaticTerrain::computeColorMap"); + for (std::size_t i = range.beginIndex; i < range.endIndex; ++i) { const float noiseValue = std::pow(vertices[i].position.y() / m_heightFactor, m_invFlatness); const Raz::Vec3b pixelValue = (noiseValue < 0.33f ? Raz::MathUtils::lerp(waterColor, grassColor, noiseValue * 3.f) @@ -141,19 +155,23 @@ const Raz::Image& StaticTerrain::computeColorMap() { } }); - m_entity.getComponent().getMaterials().front().getProgram().setTexture(Raz::Texture2D::create(m_colorMap), + m_entity.getComponent().getMaterials().front().getProgram().setTexture(Raz::Texture2D::create(m_colorMap, true, true), Raz::MaterialTexture::BaseColor); return m_colorMap; } const Raz::Image& StaticTerrain::computeNormalMap() { + ZoneScopedN("StaticTerrain::computeNormalMap"); + m_normalMap = Raz::Image(m_width, m_depth, Raz::ImageColorspace::RGB); auto* imgData = static_cast(m_normalMap.getDataPtr()); const std::vector& vertices = m_entity.getComponent().getSubmeshes().front().getVertices(); Raz::Threading::parallelize(0, vertices.size(), [&vertices, imgData] (const Raz::Threading::IndexRange& range) noexcept { + ZoneScopedN("StaticTerrain::computeNormalMap"); + for (std::size_t i = range.beginIndex; i < range.endIndex; ++i) { const Raz::Vec3f& normal = vertices[i].normal; @@ -168,27 +186,23 @@ const Raz::Image& StaticTerrain::computeNormalMap() { } const Raz::Image& StaticTerrain::computeSlopeMap() { - m_slopeMap = Raz::Image(m_width, m_depth, Raz::ImageColorspace::RGB, Raz::ImageDataType::FLOAT); - auto* imgData = static_cast(m_slopeMap.getDataPtr()); + ZoneScopedN("StaticTerrain::computeSlopeMap"); + + m_slopeMap = Raz::Image(m_width, m_depth, Raz::ImageColorspace::RGB, Raz::ImageDataType::FLOAT); const std::vector& vertices = m_entity.getComponent().getSubmeshes().front().getVertices(); for (unsigned int j = 1; j < m_depth - 1; ++j) { - const unsigned int depthStride = j * m_width * 3; - for (unsigned int i = 1; i < m_width - 1; ++i) { const float topHeight = vertices[(j - 1) * m_width + i].position.y(); const float leftHeight = vertices[j * m_width + i - 1].position.y(); const float rightHeight = vertices[j * m_width + i + 1].position.y(); const float botHeight = vertices[(j + 1) * m_width + i].position.y(); - Raz::Vec2f slopeVec(leftHeight - rightHeight, topHeight - botHeight); + const Raz::Vec2f slopeVec(leftHeight - rightHeight, topHeight - botHeight); const float slopeStrength = slopeVec.computeLength() * 0.5f; - slopeVec = slopeVec.normalize(); - imgData[depthStride + i * 3 ] = slopeVec.x(); - imgData[depthStride + i * 3 + 1] = slopeVec.y(); - imgData[depthStride + i * 3 + 2] = slopeStrength; + m_slopeMap.setPixel(i, j, Raz::Vec3f(slopeVec.normalize(), slopeStrength)); } } @@ -196,6 +210,8 @@ const Raz::Image& StaticTerrain::computeSlopeMap() { } void StaticTerrain::computeNormals() { + ZoneScopedN("StaticTerrain::computeNormals"); + std::vector& vertices = m_entity.getComponent().getSubmeshes().front().getVertices(); for (unsigned int j = 1; j < m_depth - 1; ++j) { @@ -253,10 +269,14 @@ void StaticTerrain::computeNormals() { } void StaticTerrain::remapVertices(float newHeightFactor, float newFlatness) { + ZoneScopedN("StaticTerrain::remapVertices"); + auto& mesh = m_entity.getComponent(); std::vector& vertices = mesh.getSubmeshes().front().getVertices(); Raz::Threading::parallelize(vertices, [this, newHeightFactor, newFlatness] (const auto& range) noexcept { + ZoneScopedN("StaticTerrain::remapVertices"); + for (Raz::Vertex& vertex : range) { const float baseHeight = std::pow(vertex.position.y() / m_heightFactor, m_invFlatness); vertex.position.y() = std::pow(baseHeight, newFlatness) * newHeightFactor;