summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--game/terrain.cpp79
-rw-r--r--game/terrain.h16
-rw-r--r--gfx/gl/sceneShader.cpp13
-rw-r--r--gfx/gl/sceneShader.h12
-rw-r--r--gfx/gl/shaders/landmass.fs6
-rw-r--r--gfx/gl/shaders/landmass.vs3
-rw-r--r--test/Jamfile.jam1
-rw-r--r--test/perf-terrain.cpp20
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();