From a24118baf7630eb0ab545c947d7874135a96356d Mon Sep 17 00:00:00 2001 From: maj00r Date: Tue, 3 Nov 2026 21:50:31 +0100 Subject: [PATCH] feat(render): a geometry chunk emptied in place, the kind of its primitive told; a chunk gaining or losing its userdata gets a new buffer Erase() empties a chunk and keeps its handle to be filled again, for geometry made anew as it changes. Primitive() tells whether a chunk holds triangles or strips, -1 from a renderer which doesn't know. The VAO bank reused the buffer of a chunk of the same length even when the userdata came or went, the layout of the buffer differing then. --- rendering/geometrybank.cpp | 36 ++++++++++++++++++++++++++++++ rendering/geometrybank.h | 6 +++++ rendering/opengl33geometrybank.cpp | 3 ++- rendering/opengl33renderer.cpp | 24 +++++++++++++++++++- rendering/opengl33renderer.h | 7 ++++++ rendering/openglrenderer.cpp | 5 +++++ rendering/openglrenderer.h | 1 + rendering/renderer.h | 8 +++++++ 8 files changed, 88 insertions(+), 2 deletions(-) diff --git a/rendering/geometrybank.cpp b/rendering/geometrybank.cpp index f2db8b8bf..2a1ff5ee6 100644 --- a/rendering/geometrybank.cpp +++ b/rendering/geometrybank.cpp @@ -318,6 +318,20 @@ geometry_bank::append( gfx::vertex_array &Vertices, userdata_array &Userdata, gf return replace( Vertices, Userdata, Geometry, gfx::geometry_bank::chunk( Geometry ).vertices.size() ); } +void +geometry_bank::erase( gfx::geometry_handle const &Geometry ) { + + if( ( Geometry.chunk == 0 ) || ( Geometry.chunk > m_chunks.size() ) ) { return; } + + auto &chunk = gfx::geometry_bank::chunk( Geometry ); + if( chunk.vertices.empty() && chunk.indices.empty() ) { return; } + + gfx::vertex_array().swap( chunk.vertices ); + gfx::index_array().swap( chunk.indices ); + gfx::userdata_array().swap( chunk.userdata ); + replace_( Geometry ); +} + // draws geometry stored in specified chunk std::size_t geometry_bank::draw( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) { @@ -360,6 +374,13 @@ geometry_bank::vertices( gfx::geometry_handle const &Geometry ) const { return geometry_bank::chunk( Geometry ).vertices; } +// kind of geometry of specified chunk +unsigned int +geometry_bank::primitive( gfx::geometry_handle const &Geometry ) const { + + return geometry_bank::chunk( Geometry ).type; +} + // provides direct access to vertex user data of specfied chunk userdata_array const & geometry_bank::userdata( gfx::geometry_handle const &Geometry ) const { @@ -418,6 +439,14 @@ geometrybank_manager::append( gfx::vertex_array &Vertices, userdata_array &Userd return bank( Geometry ).first->append( Vertices, Userdata, Geometry ); } + +void +geometrybank_manager::erase( gfx::geometry_handle const &Geometry ) { + + if( ( Geometry.bank == 0 ) || ( Geometry.bank > m_geometrybanks.size() ) ) { return; } + + bank( Geometry ).first->erase( Geometry ); +} // draws geometry stored in specified chunk void geometrybank_manager::draw( gfx::geometry_handle const &Geometry, unsigned int const Streams ) { @@ -483,6 +512,13 @@ geometrybank_manager::vertices( gfx::geometry_handle const &Geometry ) const { return bank( Geometry ).first->vertices( Geometry ); } +// kind of geometry of specified chunk +unsigned int +geometrybank_manager::primitive( gfx::geometry_handle const &Geometry ) const { + + return bank( Geometry ).first->primitive( Geometry ); +} + // provides direct access to vertex user data of specfied chunk gfx::userdata_array const & geometrybank_manager::userdata( gfx::geometry_handle const &Geometry ) const { diff --git a/rendering/geometrybank.h b/rendering/geometrybank.h index 20baf4ed2..537c79ba2 100644 --- a/rendering/geometrybank.h +++ b/rendering/geometrybank.h @@ -117,6 +117,7 @@ public: auto replace( gfx::vertex_array &Vertices, gfx::userdata_array& Userdata, gfx::geometry_handle const &Geometry, std::size_t const Offset = 0 ) -> bool; // adds supplied vertex data at the end of specified chunk auto append( gfx::vertex_array &Vertices, gfx::userdata_array& Userdata, gfx::geometry_handle const &Geometry ) -> bool; + void erase( gfx::geometry_handle const &Geometry ); // draws geometry stored in specified chunk auto draw( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams = basic_streams ) -> std::size_t; // draws geometry stored in specified chunk N times via glDrawElementsInstanced* @@ -138,6 +139,8 @@ public: auto vertices( gfx::geometry_handle const &Geometry ) const -> gfx::vertex_array const &; // provides direct access to vertex user data of specfied chunk auto userdata( gfx::geometry_handle const &Geometry ) const -> gfx::userdata_array const &; + // kind of geometry of specified chunk, GL_TRIANGLES, GL_TRIANGLE_STRIP... + auto primitive( gfx::geometry_handle const &Geometry ) const -> unsigned int; protected: // types: @@ -220,6 +223,7 @@ public: auto replace( gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, std::size_t const Offset = 0 ) -> bool; // adds supplied vertex data at the end of specified chunk auto append( gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry ) -> bool; + void erase( gfx::geometry_handle const &Geometry ); // draws geometry stored in specified chunk void draw( gfx::geometry_handle const &Geometry, unsigned int const Streams = basic_streams ); // draws geometry stored in specified chunk InstanceCount times via GPU instancing. @@ -238,6 +242,8 @@ public: auto vertices( gfx::geometry_handle const &Geometry ) const -> gfx::vertex_array const &; // provides direct access to vertex data of specfied chunk auto userdata( gfx::geometry_handle const &Geometry ) const -> gfx::userdata_array const &; + // kind of geometry of specified chunk + auto primitive( gfx::geometry_handle const &Geometry ) const -> unsigned int; // sets target texture unit for the texture data stream auto units() -> gfx::stream_units & { return m_units; } // provides access to primitives count diff --git a/rendering/opengl33geometrybank.cpp b/rendering/opengl33geometrybank.cpp index 4713ec69b..978a1b75d 100644 --- a/rendering/opengl33geometrybank.cpp +++ b/rendering/opengl33geometrybank.cpp @@ -33,7 +33,8 @@ opengl33_vaogeometrybank::replace_( gfx::geometry_handle const &Geometry ) { auto &chunkrecord = m_chunkrecords[ Geometry.chunk - 1 ]; chunkrecord.is_good = false; // if the overall length of the chunk didn't change we can get away with reusing the old buffer... - if( geometry_bank::chunk( Geometry ).vertices.size() != chunkrecord.vertex_count ) { + if( ( geometry_bank::chunk( Geometry ).vertices.size() != chunkrecord.vertex_count ) + || ( geometry_bank::chunk( Geometry ).userdata.empty() == chunkrecord.has_userdata ) ) { // ...but otherwise we'll need to allocate a new one // TBD: we could keep and reuse the old buffer also if the new chunk is smaller than the old one, // but it'd require some extra tracking and work to keep all chunks up to date; also wasting vram; may be not worth it? diff --git a/rendering/opengl33renderer.cpp b/rendering/opengl33renderer.cpp index d20454c35..97b2fa8d2 100644 --- a/rendering/opengl33renderer.cpp +++ b/rendering/opengl33renderer.cpp @@ -2201,8 +2201,13 @@ bool opengl33_renderer::Append(gfx::vertex_array &Vertices, gfx::userdata_array return m_geometry.append(Vertices, Userdata, Geometry); } +void opengl33_renderer::Erase(gfx::geometry_handle const &Geometry) +{ + m_geometry.erase(Geometry); +} + // provides direct access to index data of specfied chunk -gfx::index_array const & opengl33_renderer::Indices(gfx::geometry_handle const &Geometry) const +gfx::index_array const & opengl33_renderer::Indices(gfx::geometry_handle const &Geometry) const { return m_geometry.indices(Geometry); } @@ -2218,6 +2223,11 @@ gfx::userdata_array const &opengl33_renderer::UserData(const gfx::geometry_handl return m_geometry.userdata(Geometry); } +int opengl33_renderer::Primitive(gfx::geometry_handle const &Geometry) const +{ + return static_cast(m_geometry.primitive(Geometry)); +} + // material methods material_handle opengl33_renderer::Fetch_Material(std::string const &Filename, bool const Loadnow) { @@ -2225,6 +2235,18 @@ material_handle opengl33_renderer::Fetch_Material(std::string const &Filename, b return m_materials.create(Filename, Loadnow); } +material_handle opengl33_renderer::Matte_Material(material_handle const Material) +{ + + return m_materials.create_matte(Material); +} + +material_handle opengl33_renderer::Tinted_Material(material_handle const Material, glm::vec3 const &Colour) +{ + + return m_materials.create_tinted(Material, Colour); +} + std::shared_ptr opengl33_renderer::Fetch_Shader(const std::string &name) { auto it = m_shaders.find(name); diff --git a/rendering/opengl33renderer.h b/rendering/opengl33renderer.h index 64574420f..b04153586 100644 --- a/rendering/opengl33renderer.h +++ b/rendering/opengl33renderer.h @@ -66,6 +66,7 @@ class opengl33_renderer : public gfx_renderer { bool Replace(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type, const std::size_t Offset = 0) override; // adds supplied vertex data at the end of specified chunk bool Append(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type) override; + void Erase( gfx::geometry_handle const &Geometry ) override; // provides direct access to index data of specfied chunk gfx::index_array const & Indices( gfx::geometry_handle const &Geometry ) const override; @@ -75,9 +76,15 @@ class opengl33_renderer : public gfx_renderer { // provides direct access to vertex data of specfied chunk gfx::userdata_array const & UserData( gfx::geometry_handle const &Geometry ) const override; + int + Primitive( gfx::geometry_handle const &Geometry ) const override; // material methods material_handle Fetch_Material( std::string const &Filename, bool const Loadnow = true ) override; + material_handle + Matte_Material( material_handle const Material ) override; + material_handle + Tinted_Material( material_handle const Material, glm::vec3 const &Colour ) override; void Bind_Material( material_handle const Material, TSubModel const *sm = nullptr, lighting_data const *lighting = nullptr ) override; IMaterial const * diff --git a/rendering/openglrenderer.cpp b/rendering/openglrenderer.cpp index 59152c64d..51ac1e715 100644 --- a/rendering/openglrenderer.cpp +++ b/rendering/openglrenderer.cpp @@ -1758,6 +1758,11 @@ bool opengl_renderer::Append(gfx::vertex_array &Vertices, gfx::userdata_array &U return m_geometry.append( Vertices, Userdata, Geometry ); } +void opengl_renderer::Erase( gfx::geometry_handle const &Geometry ) +{ + m_geometry.erase( Geometry ); +} + // provides direct access to vertex data of specfied chunk gfx::index_array const & opengl_renderer::Indices( gfx::geometry_handle const &Geometry ) const { diff --git a/rendering/openglrenderer.h b/rendering/openglrenderer.h index 78fffa40b..da3faad06 100644 --- a/rendering/openglrenderer.h +++ b/rendering/openglrenderer.h @@ -65,6 +65,7 @@ public: bool Replace(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type, const std::size_t Offset = 0) override; // adds supplied vertex data at the end of specified chunk bool Append(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type) override; + void Erase( gfx::geometry_handle const &Geometry ) override; // provides direct access to index data of specfied chunk gfx::index_array const & Indices( gfx::geometry_handle const &Geometry ) const override; diff --git a/rendering/renderer.h b/rendering/renderer.h index 0b9eb60f4..4dabc204a 100644 --- a/rendering/renderer.h +++ b/rendering/renderer.h @@ -59,16 +59,24 @@ public: virtual auto Replace(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type, const std::size_t Offset = 0) -> bool = 0; // adds supplied vertex data at the end of specified chunk virtual auto Append(gfx::vertex_array &Vertices, gfx::userdata_array &Userdata, gfx::geometry_handle const &Geometry, int const Type) -> bool = 0; + // empties specified chunk, its handle stays valid to be filled again + virtual void Erase( gfx::geometry_handle const &Geometry ) {} // provides direct access to index data of specfied chunk virtual auto Indices( gfx::geometry_handle const &Geometry ) const->gfx::index_array const & = 0; // provides direct access to vertex data of specfied chunk virtual auto Vertices( gfx::geometry_handle const &Geometry ) const ->gfx::vertex_array const & = 0; // provides direct access to vertex user data of specfied chunk virtual auto UserData( gfx::geometry_handle const &Geometry ) const ->gfx::userdata_array const & = 0; + // kind of geometry of specified chunk, -1 when the renderer doesn't tell + virtual auto Primitive( gfx::geometry_handle const &Geometry ) const -> int { return -1; } // material methods virtual auto Fetch_Material( std::string const &Filename, bool const Loadnow = true ) -> material_handle = 0; virtual void Bind_Material( material_handle const Material, TSubModel const *sm = nullptr, lighting_data const *lighting = nullptr ) = 0; virtual auto Material( material_handle const Material ) const -> IMaterial const * = 0; + // the same material with its highlights damped, for faces which aren't polished like the surfaces they are cut from. backends which can't make one give back the material itself + virtual auto Matte_Material( material_handle const Material ) -> material_handle { return Material; } + // the same material with its texture tinted by the colour, as far as the userdata of the vertices says. backends which can't make one give back the material itself + virtual auto Tinted_Material( material_handle const Material, glm::vec3 const &Colour ) -> material_handle { return Material; } // heightmap terrain: material of a chunk blending the materials of up to 8 layers by their weights. // Weights: (Samples + 1)^2 values per layer, planar, rows of growing z, the weights of a sample adding up to 255; null with a single layer. // Placement: corner of the chunk (x, z) in the texture coordinates of its mesh, and the size of the chunk.