summaryrefslogtreecommitdiff
path: root/game/terrain.cpp
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2025-02-25 00:23:11 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2025-02-25 00:23:11 +0000
commitf9962b0db5072870864a1f758687106139f740dc (patch)
treeae1b05395de5c07164151ef7fc7de202be19b9f0 /game/terrain.cpp
parentAdd VertexArrayObject::data for an external existing buffer (diff)
downloadilt-f9962b0db5072870864a1f758687106139f740dc.tar.bz2
ilt-f9962b0db5072870864a1f758687106139f740dc.tar.xz
ilt-f9962b0db5072870864a1f758687106139f740dc.zip
Improve Terrain::generateMeshes performanceHEADmain
Creates mesh per surface based on a single buffer of all vertices and a collection of per surfuce indices. Makes ColourBias a uniform instead of a vertex attribute.
Diffstat (limited to 'game/terrain.cpp')
-rw-r--r--game/terrain.cpp79
1 files changed, 50 insertions, 29 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);
}