feat: instance + array buffer

This commit is contained in:
2025-10-24 13:06:40 +02:00
parent b5ea21ad43
commit e459fea503
7 changed files with 67 additions and 35 deletions

View File

@ -11,24 +11,19 @@ batch::batch() {
}
void batch::prepare(glm::mat4 *instances, unsigned int count) {
if (m_instance_vbo == 0) {
glGenBuffers(1, &m_instance_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_instance_vbo);
// Allocate *once*, no data yet — just reserve space
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * count, nullptr, GL_DYNAMIC_DRAW);
if (!m_instanceBuffer) {
m_instanceBuffer = std::make_unique<OpenGL::InstanceBuffer>(GL_DYNAMIC_DRAW);
m_instanceBuffer->Data(nullptr, sizeof(glm::mat4) * count);
m_instance_count = count;
} else if (count > m_instance_count) {
// Optional: reallocate only if you *really* have more instances than before
glBindBuffer(GL_ARRAY_BUFFER, m_instance_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * count, nullptr, GL_DYNAMIC_DRAW);
m_instanceBuffer->Data(nullptr, sizeof(glm::mat4) * count);
m_instance_count = count;
} else {
glBindBuffer(GL_ARRAY_BUFFER, m_instance_vbo);
}
// Just update the data region — much cheaper
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(glm::mat4) * count, instances);
glBindBuffer(GL_ARRAY_BUFFER, 0);
m_instanceBuffer->SubData(instances, sizeof(glm::mat4) * count, 0);
}
}

View File

@ -13,11 +13,11 @@ namespace OpenGL {
Unbind();
}
void Buffer::Bind() {
void Buffer::Bind() const {
glBindBuffer(m_target, m_buffer);
}
void Buffer::Unbind() {
void Buffer::Unbind() const {
glBindBuffer(m_target, 0);
}
@ -33,13 +33,13 @@ namespace OpenGL {
Unbind();
}
void Buffer::BindBuffer(unsigned int index) {
void Buffer::BindBuffer(unsigned int index) const {
Bind();
glBindBufferBase(m_target, index, m_buffer);
Unbind();
}
void Buffer::BindBufferRanged(unsigned int index, size_t offset, size_t size) {
void Buffer::BindBufferRanged(unsigned int index, size_t offset, size_t size) const {
Bind();
glBindBufferRange(m_target, index, m_buffer, offset, size);
Unbind();
@ -55,11 +55,17 @@ namespace OpenGL {
BindBuffer(m_uniformBinding);
}
void UniformBuffer::ConfigureShader(Shader& shader, const char* uniformName) {
void UniformBuffer::ConfigureShader(Shader& shader, const char* uniformName) const {
auto uniformIndex = glGetUniformBlockIndex(shader.GetID(), uniformName);
glUniformBlockBinding(shader.GetID(), uniformIndex, m_uniformBinding);
}
ArrayBuffer::ArrayBuffer(BufferUsage usage)
: Buffer(GL_ARRAY_BUFFER, usage) {}
InstanceBuffer::InstanceBuffer(BufferUsage usage)
: ArrayBuffer(usage) {}
} // namespace OpenGL
} // namespace Core

View File

@ -166,11 +166,11 @@ void Renderer::RenderScene(Shader &shader) {
models.push_back(itemModel);
}
auto prevInstanceVBO = b.m_instance_vbo;
auto prevState = b.Initialized();
b.prepare(models.data(), models.size());
if (prevInstanceVBO <= 0) {
if (!prevState) {
std::cout << "[DEBUG] enabling batch" << std::endl;
m.object->EnableBatch(b.m_instance_vbo);
m.object->EnableBatch(b.m_instanceBuffer.get());
}
m.object->Render(shader, batchItems.size());
}

View File

@ -397,19 +397,19 @@ Object* Object::LoadFile(const std::string& filename) {
return obj;
}
void Object::EnableBatch(unsigned int instanceVBO) {
void Object::EnableBatch(const OpenGL::InstanceBuffer* instanceBuffer) {
for (auto &mesh : m_meshes) {
mesh.Bind();
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
std::size_t vec4Size = sizeof(glm::vec4);
for (int i = 0; i < 4; ++i) {
glEnableVertexAttribArray(3 + i); // use locations 3,4,5,6 for instance matrix
glVertexAttribPointer(3 + i, 4, GL_FLOAT, GL_FALSE,
sizeof(glm::mat4), (void*)(i * vec4Size));
glVertexAttribDivisor(3 + i, 1); // IMPORTANT: one per instance, not per vertex
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
instanceBuffer->StartConfigure();
std::size_t vec4Size = sizeof(glm::vec4);
for (int i = 0; i < 4; ++i) {
glEnableVertexAttribArray(3 + i); // use locations 3,4,5,6 for instance matrix
glVertexAttribPointer(3 + i, 4, GL_FLOAT, GL_FALSE,
sizeof(glm::mat4), (void*)(i * vec4Size));
glVertexAttribDivisor(3 + i, 1); // IMPORTANT: one per instance, not per vertex
}
instanceBuffer->EndConfigure();
mesh.Unbind();
}