diff options
-rw-r--r-- | game/terrain.cpp | 79 | ||||
-rw-r--r-- | game/terrain.h | 16 | ||||
-rw-r--r-- | gfx/gl/sceneShader.cpp | 13 | ||||
-rw-r--r-- | gfx/gl/sceneShader.h | 12 | ||||
-rw-r--r-- | gfx/gl/shaders/landmass.fs | 6 | ||||
-rw-r--r-- | gfx/gl/shaders/landmass.vs | 3 | ||||
-rw-r--r-- | test/Jamfile.jam | 1 | ||||
-rw-r--r-- | test/perf-terrain.cpp | 20 |
8 files changed, 105 insertions, 45 deletions
diff --git a/game/terrain.cpp b/game/terrain.cpp index 01af163..c28f7ee 100644 --- a/game/terrain.cpp +++ b/game/terrain.cpp @@ -1,12 +1,11 @@ #include "terrain.h" -#include "game/geoData.h" #include <algorithm> -#include <cstddef> #include <gfx/gl/sceneShader.h> #include <gfx/gl/shadowMapper.h> #include <gfx/image.h> #include <gfx/models/mesh.h> #include <gfx/models/vertex.h> +#include <glMappedBufferWriter.h> #include <glm/glm.hpp> #include <iterator> #include <location.h> @@ -20,37 +19,51 @@ template<> VertexArrayObject & VertexArrayObject::addAttribsFor<Terrain::Vertex>(const GLuint arrayBuffer, const GLuint divisor) { - return addAttribs<Terrain::Vertex, &Terrain::Vertex::pos, &Terrain::Vertex::normal, &Terrain::Vertex::colourBias>( - arrayBuffer, divisor); + return addAttribs<Terrain::Vertex, &Terrain::Vertex::pos, &Terrain::Vertex::normal>(arrayBuffer, divisor); } void Terrain::generateMeshes() { - meshes.removeAll(); - std::vector<unsigned int> indices; - indices.reserve(n_faces() * 3); - std::vector<Vertex> vertices; - vertices.reserve(n_vertices()); - std::map<std::pair<VertexHandle, const Surface *>, size_t> vertexIndex; - std::ranges::for_each(this->vertices(), [this, &vertexIndex, &vertices](const auto vertex) { - std::ranges::for_each(vf_range(vertex), [&vertexIndex, vertex, this, &vertices](const auto face) { - const auto * const surface = getSurface(face); - if (const auto vertexIndexRef = vertexIndex.emplace(std::make_pair(vertex, surface), 0); - vertexIndexRef.second) { - vertexIndexRef.first->second = vertices.size(); + std::ranges::transform(all_vertices(), glMappedBufferWriter<Vertex> {GL_ARRAY_BUFFER, verticesBuffer, n_vertices()}, + [this](const auto & vertex) { + return Vertex {point(vertex), normal(vertex)}; + }); - vertices.emplace_back(point(vertex), normal(vertex), surface ? surface->colorBias : OPEN_SURFACE); + std::map<const Surface *, std::vector<GLuint>> surfaceIndices; + for (const auto face : faces()) { + const auto * const surface = getSurface(face); + auto indexItr = surfaceIndices.find(surface); + if (indexItr == surfaceIndices.end()) { + indexItr = surfaceIndices.emplace(surface, std::vector<GLuint> {}).first; + if (!surface) { + indexItr->second.reserve(n_vertices() * 3); } + } + std::ranges::transform(fv_range(face), std::back_inserter(indexItr->second), &OpenMesh::VertexHandle::idx); + } + + for (const auto & [surface, indices] : surfaceIndices) { + auto meshItr = meshes.find(surface); + if (meshItr == meshes.end()) { + meshItr = meshes.emplace(surface, SurfaceArrayBuffer {}); + VertexArrayObject {meshItr->second.vertexArray} + .addAttribsFor<Vertex>(verticesBuffer) + .addIndices(meshItr->second.indicesBuffer, indices) + .data(verticesBuffer, GL_ARRAY_BUFFER); + } + else { + VertexArrayObject {meshItr->second.vertexArray} + .addIndices(meshItr->second.indicesBuffer, indices) + .data(verticesBuffer, GL_ARRAY_BUFFER); + } + meshItr->second.count = static_cast<GLsizei>(indices.size()); + } + if (meshes.size() > surfaceIndices.size()) { + std::erase_if(meshes, [&surfaceIndices](const auto & mesh) { + return !surfaceIndices.contains(mesh.first); }); - }); - std::ranges::for_each(faces(), [this, &vertexIndex, &indices](const auto face) { - std::ranges::transform( - fv_range(face), std::back_inserter(indices), [&vertexIndex, face, this](const auto vertex) { - return vertexIndex[std::make_pair(vertex, getSurface(face))]; - }); - }); - meshes.create<MeshT<Vertex>>(vertices, indices); + } } void @@ -61,20 +74,28 @@ Terrain::tick(TickDuration) void Terrain::afterChange() { - generateMeshes(); + generateMeshes(); } void Terrain::render(const SceneShader & shader) const { - shader.landmass.use(); grass->bind(); - meshes.apply(&Mesh::Draw); + for (const auto & [surface, sab] : meshes) { + shader.landmass.use(surface ? surface->colorBias : OPEN_SURFACE); + glBindVertexArray(sab.vertexArray); + glDrawElements(GL_TRIANGLES, sab.count, GL_UNSIGNED_INT, nullptr); + } + glBindVertexArray(0); } void Terrain::shadows(const ShadowMapper & shadowMapper) const { shadowMapper.landmess.use(); - meshes.apply(&Mesh::Draw); + for (const auto & [surface, sab] : meshes) { + glBindVertexArray(sab.vertexArray); + glDrawElements(GL_TRIANGLES, sab.count, GL_UNSIGNED_INT, nullptr); + } + glBindVertexArray(0); } diff --git a/game/terrain.h b/game/terrain.h index f0f9621..095b4ef 100644 --- a/game/terrain.h +++ b/game/terrain.h @@ -1,11 +1,9 @@ #pragma once #include "chronology.h" -#include "collection.h" #include "config/types.h" #include "game/worldobject.h" #include "geoData.h" -#include "gfx/models/mesh.h" #include "gfx/models/texture.h" #include "gfx/renderable.h" @@ -26,14 +24,20 @@ public: struct Vertex { GlobalPosition3D pos; Normal3D normal; - RGB colourBias; }; + void generateMeshes(); + private: void afterChange() override; - void generateMeshes(); - Collection<MeshT<Vertex>, false> meshes; + struct SurfaceArrayBuffer { + glVertexArray vertexArray; + glBuffer indicesBuffer; + GLsizei count; + }; + + glBuffer verticesBuffer; + std::multimap<const Surface *, SurfaceArrayBuffer> meshes; Texture::Ptr grass = std::make_shared<Texture>("grass.png"); - size_t geoGeneration {}; }; diff --git a/gfx/gl/sceneShader.cpp b/gfx/gl/sceneShader.cpp index 571538a..4b82ae4 100644 --- a/gfx/gl/sceneShader.cpp +++ b/gfx/gl/sceneShader.cpp @@ -34,9 +34,9 @@ SceneShader::allPrograms(auto member, auto &&... ps) const } SceneShader::SceneShader() : - basicInst {dynamicPointInst_vs, material_fs}, landmass {landmass_vs, landmass_fs}, - absolute {fixedPoint_vs, material_fs}, spotLightInst {spotLight_vs, spotLight_gs, spotLight_fs}, - pointLightInst {pointLight_vs, pointLight_gs, pointLight_fs}, + basicInst {dynamicPointInst_vs, material_fs}, absolute {fixedPoint_vs, material_fs}, + spotLightInst {spotLight_vs, spotLight_gs, spotLight_fs}, + pointLightInst {pointLight_vs, pointLight_gs, pointLight_fs}, landmass {landmass_vs, landmass_fs}, networkStraight {networkStraight_vs, networkStraight_gs, network_fs}, networkCurve {networkCurve_vs, networkCurve_gs, network_fs} { @@ -88,6 +88,13 @@ SceneShader::BasicProgram::use(Location const & location) const } void +SceneShader::LandmassProgram::use(const glm::vec3 colourBias) const +{ + Program::use(); + glUniform(colourBiasLos, colourBias); +} + +void SceneShader::NetworkProgram::use( const std::span<const glm::vec3> profile, const std::span<const float> texturePos) const { diff --git a/gfx/gl/sceneShader.h b/gfx/gl/sceneShader.h index 51f0e21..47d4397 100644 --- a/gfx/gl/sceneShader.h +++ b/gfx/gl/sceneShader.h @@ -50,6 +50,15 @@ class SceneShader { RequiredUniformLocation profileLengthLoc {*this, "profileLength"}; }; + class LandmassProgram : public AbsolutePosProgram { + public: + using AbsolutePosProgram::AbsolutePosProgram; + void use(const glm::vec3) const; + + private: + RequiredUniformLocation colourBiasLos {*this, "colourBias"}; + }; + class WaterProgram : public SceneProgram { public: WaterProgram(); @@ -64,7 +73,8 @@ public: BasicProgram basic; WaterProgram water; - AbsolutePosProgram basicInst, landmass, absolute, spotLightInst, pointLightInst; + AbsolutePosProgram basicInst, absolute, spotLightInst, pointLightInst; + LandmassProgram landmass; NetworkProgram networkStraight, networkCurve; void setViewProjection(const GlobalPosition3D & viewPoint, const glm::mat4 & viewProjection) const; diff --git a/gfx/gl/shaders/landmass.fs b/gfx/gl/shaders/landmass.fs index 55e3c24..382260e 100644 --- a/gfx/gl/shaders/landmass.fs +++ b/gfx/gl/shaders/landmass.fs @@ -3,10 +3,10 @@ include(`materialOut.glsl') in vec3 FragPos; in vec3 Normal; -flat in vec3 ColourBias; uniform sampler2D texture0; uniform ivec3 viewPoint; +uniform vec3 colourBias; const vec3 grass = vec3(.1, .4, .05); const vec3 slope = vec3(.6, .6, .4); @@ -35,8 +35,8 @@ main() vec3 color = texture(texture0, vec2(position.xy % 10000) / 10000.0).rgb; int height = position.z; - if (ColourBias.r >= 0) { - color *= ColourBias; + if (colourBias.r >= 0) { + color *= colourBias; } else if (height < beachline) { // Sandy beach color *= sand; diff --git a/gfx/gl/shaders/landmass.vs b/gfx/gl/shaders/landmass.vs index 9617cb9..44cb879 100644 --- a/gfx/gl/shaders/landmass.vs +++ b/gfx/gl/shaders/landmass.vs @@ -3,11 +3,9 @@ layout(location = 0) in ivec3 position; layout(location = 1) in vec3 normal; -layout(location = 2) in vec3 colourBias; out vec3 FragPos; out vec3 Normal; -flat out vec3 ColourBias; uniform mat4 viewProjection; uniform ivec3 viewPoint; @@ -17,7 +15,6 @@ main() { FragPos = position - viewPoint; Normal = normal; - ColourBias = colourBias; gl_Position = viewProjection * vec4(FragPos, 1); } diff --git a/test/Jamfile.jam b/test/Jamfile.jam index c5c49d2..8219398 100644 --- a/test/Jamfile.jam +++ b/test/Jamfile.jam @@ -57,6 +57,7 @@ run test-glContextBhvr.cpp ; run test-assetFactory.cpp : -- : [ sequence.insertion-sort [ glob-tree $(res) : *.* ] fixtures/rgb.txt test-instancing ] : <library>test ; run perf-assetFactory.cpp : \< : test-assetFactory : <library>benchmark <library>test ; run perf-geoData.cpp : \< : test-geoData : <library>test <library>benchmark ; +run perf-terrain.cpp : \< : test-geoData : <library>test <library>benchmark ; run perf-persistence.cpp : \< : test-persistence : <library>benchmark <library>test ; run test-worker.cpp ; run test-instancing.cpp : -- : test-glContainer : <library>test ; diff --git a/test/perf-terrain.cpp b/test/perf-terrain.cpp new file mode 100644 index 0000000..dbd44fa --- /dev/null +++ b/test/perf-terrain.cpp @@ -0,0 +1,20 @@ +#include "game/terrain.h" +#include "testMainWindow.h" +#include <benchmark/benchmark.h> + +namespace { + void + terrainMeshgen(benchmark::State & state) + { + TestMainWindowAppBase window; + Terrain terrain {GeoData::loadFromAsciiGrid(FIXTURESDIR "height/SD19.asc")}; + + for (auto _ : state) { + terrain.generateMeshes(); + } + } +} + +BENCHMARK(terrainMeshgen); + +BENCHMARK_MAIN(); |