ADD: VAO and VBO classes for OpenGL
This commit is contained in:
parent
8ae128e0ee
commit
081a091f37
@ -89,6 +89,12 @@ add_library(Engine STATIC
|
|||||||
engine/src/utils/openglWrapper/GLRenderState.h
|
engine/src/utils/openglWrapper/GLRenderState.h
|
||||||
engine/src/utils/openglWrapper/openglObjects/Attribute.cpp
|
engine/src/utils/openglWrapper/openglObjects/Attribute.cpp
|
||||||
engine/src/utils/openglWrapper/openglObjects/Attribute.h
|
engine/src/utils/openglWrapper/openglObjects/Attribute.h
|
||||||
|
engine/src/utils/openglWrapper/openglObjects/Vbo.cpp
|
||||||
|
engine/src/utils/openglWrapper/openglObjects/Vbo.h
|
||||||
|
engine/src/utils/openglWrapper/openglObjects/Vao.cpp
|
||||||
|
engine/src/utils/openglWrapper/openglObjects/Vao.h
|
||||||
|
engine/src/utils/openglWrapper/shader/ShaderProgram.cpp
|
||||||
|
engine/src/utils/openglWrapper/shader/ShaderProgram.h
|
||||||
)
|
)
|
||||||
target_include_directories(Engine PUBLIC engine/src)
|
target_include_directories(Engine PUBLIC engine/src)
|
||||||
target_link_libraries(Engine PUBLIC OpenGL::GL glfw glad glm::glm imgui)
|
target_link_libraries(Engine PUBLIC OpenGL::GL glfw glad glm::glm imgui)
|
||||||
@ -98,8 +104,7 @@ add_executable(ColorRace
|
|||||||
game/src/main.cpp
|
game/src/main.cpp
|
||||||
game/src/ColorRaceApp.cpp
|
game/src/ColorRaceApp.cpp
|
||||||
game/src/ColorRaceApp.h
|
game/src/ColorRaceApp.h
|
||||||
engine/src/utils/openglWrapper/shader/ShaderProgram.cpp
|
|
||||||
engine/src/utils/openglWrapper/shader/ShaderProgram.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(ColorRace PRIVATE
|
target_link_libraries(ColorRace PRIVATE
|
||||||
|
|||||||
@ -16,6 +16,8 @@ namespace engine {
|
|||||||
|
|
||||||
void enable(bool enable) const;
|
void enable(bool enable) const;
|
||||||
virtual void link(int offset, int stride);
|
virtual void link(int offset, int stride);
|
||||||
|
int getBytesPerVertex() const { return m_bytesPerVertex; }
|
||||||
|
unsigned int getAttributeNumber() const { return m_attributeNumber; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned int m_attributeNumber;
|
unsigned int m_attributeNumber;
|
||||||
|
|||||||
136
engine/src/utils/openglWrapper/openglObjects/Vao.cpp
Normal file
136
engine/src/utils/openglWrapper/openglObjects/Vao.cpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 29.07.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Vao.h"
|
||||||
|
#include "Vao.h"
|
||||||
|
|
||||||
|
namespace engine {
|
||||||
|
|
||||||
|
Vao::Vao(unsigned int id) : m_id(id) {
|
||||||
|
bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vao::~Vao() {
|
||||||
|
glDeleteVertexArrays(1, &m_id);
|
||||||
|
// m_relatedVbos und m_indexBuffer räumen sich selbst auf (unique_ptr, RAII)
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Vao> Vao::create() {
|
||||||
|
unsigned int id;
|
||||||
|
glGenVertexArrays(1, &id);
|
||||||
|
return std::unique_ptr<Vao>(new Vao(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vao::bind() const {
|
||||||
|
glBindVertexArray(m_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vao::unbind() const {
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vao::enableAttributes() const {
|
||||||
|
for (const auto& attribute : m_attributes) {
|
||||||
|
attribute->enable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vao::disableAttributes(const std::vector<unsigned int>& attribNumbers) const {
|
||||||
|
for (unsigned int i : attribNumbers) {
|
||||||
|
glDisableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Vao::getVertexDataTotalBytes(const std::vector<std::unique_ptr<Attribute>>& attributes) {
|
||||||
|
int total = 0;
|
||||||
|
for (const auto& attribute : attributes) {
|
||||||
|
total += attribute->getBytesPerVertex();
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vao::linkAttributes(int bytesPerVertex, std::vector<std::unique_ptr<Attribute>>& newAttributes) {
|
||||||
|
int offset = 0;
|
||||||
|
for (auto& attribute : newAttributes) {
|
||||||
|
attribute->link(offset, bytesPerVertex);
|
||||||
|
offset += attribute->getBytesPerVertex();
|
||||||
|
attribute->enable(true);
|
||||||
|
m_attributes.push_back(std::move(attribute));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vao::indicateInstancedAttributes(const std::vector<std::unique_ptr<Attribute>>& attributes) const {
|
||||||
|
for (const auto& attribute : attributes) {
|
||||||
|
glVertexAttribDivisor(attribute->getAttributeNumber(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vbo& Vao::createDataFeed(size_t maxVertexCount, GLenum usage,
|
||||||
|
std::vector<std::unique_ptr<Attribute>> newAttributes) {
|
||||||
|
int bytesPerVertex = getVertexDataTotalBytes(newAttributes);
|
||||||
|
auto vbo = Vbo::create(GL_ARRAY_BUFFER, usage);
|
||||||
|
vbo->allocateData(bytesPerVertex * maxVertexCount);
|
||||||
|
linkAttributes(bytesPerVertex, newAttributes);
|
||||||
|
vbo->unbind();
|
||||||
|
|
||||||
|
m_relatedVbos.push_back(std::move(vbo));
|
||||||
|
return *m_relatedVbos.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vbo& Vao::createInstanceDataFeed(size_t maxInstances,
|
||||||
|
std::vector<std::unique_ptr<Attribute>> newAttributes) {
|
||||||
|
int bytesPerInstance = getVertexDataTotalBytes(newAttributes);
|
||||||
|
auto vbo = Vbo::create(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW);
|
||||||
|
vbo->allocateData(bytesPerInstance * maxInstances);
|
||||||
|
linkAttributes(bytesPerInstance, newAttributes);
|
||||||
|
indicateInstancedAttributes(newAttributes);
|
||||||
|
vbo->unbind();
|
||||||
|
|
||||||
|
m_relatedVbos.push_back(std::move(vbo));
|
||||||
|
return *m_relatedVbos.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vbo& Vao::initDataFeed(const void* data, size_t sizeInBytes, GLenum usage,
|
||||||
|
std::vector<std::unique_ptr<Attribute>> newAttributes) {
|
||||||
|
int bytesPerVertex = getVertexDataTotalBytes(newAttributes);
|
||||||
|
auto vbo = Vbo::create(GL_ARRAY_BUFFER, usage);
|
||||||
|
vbo->allocateAndStoreData(data, sizeInBytes);
|
||||||
|
linkAttributes(bytesPerVertex, newAttributes);
|
||||||
|
vbo->unbind();
|
||||||
|
|
||||||
|
m_relatedVbos.push_back(std::move(vbo));
|
||||||
|
return *m_relatedVbos.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vao::linkBoundVbo(std::unique_ptr<Vbo> vbo,
|
||||||
|
std::vector<std::unique_ptr<Attribute>> newAttributes) {
|
||||||
|
int bytesPerVertex = getVertexDataTotalBytes(newAttributes);
|
||||||
|
linkAttributes(bytesPerVertex, newAttributes);
|
||||||
|
m_relatedVbos.push_back(std::move(vbo));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vao::linkInstancingVbo(std::unique_ptr<Vbo> vbo,
|
||||||
|
std::vector<std::unique_ptr<Attribute>> newAttributes) {
|
||||||
|
vbo->bind();
|
||||||
|
int bytesPerVertex = getVertexDataTotalBytes(newAttributes);
|
||||||
|
linkAttributes(bytesPerVertex, newAttributes);
|
||||||
|
indicateInstancedAttributes(newAttributes);
|
||||||
|
vbo->unbind();
|
||||||
|
|
||||||
|
m_relatedVbos.push_back(std::move(vbo));
|
||||||
|
}
|
||||||
|
|
||||||
|
Vbo& Vao::createIndexBuffer(const unsigned int* indices, size_t count) {
|
||||||
|
m_indexBuffer = Vbo::create(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW);
|
||||||
|
m_indexBuffer->allocateAndStoreData(indices, count * sizeof(unsigned int));
|
||||||
|
return *m_indexBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vbo& Vao::createIndexBufferFeed(size_t maxIndexCount) {
|
||||||
|
m_indexBuffer = Vbo::create(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW);
|
||||||
|
m_indexBuffer->allocateData(maxIndexCount * sizeof(unsigned int));
|
||||||
|
return *m_indexBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace engine
|
||||||
70
engine/src/utils/openglWrapper/openglObjects/Vao.h
Normal file
70
engine/src/utils/openglWrapper/openglObjects/Vao.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 29.07.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COLORRACE_VAO_H
|
||||||
|
#define COLORRACE_VAO_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include "Vbo.h"
|
||||||
|
#include "Attribute.h"
|
||||||
|
|
||||||
|
namespace engine {
|
||||||
|
|
||||||
|
class Vao {
|
||||||
|
public:
|
||||||
|
static std::unique_ptr<Vao> create();
|
||||||
|
|
||||||
|
~Vao();
|
||||||
|
|
||||||
|
Vao(const Vao&) = delete;
|
||||||
|
Vao& operator=(const Vao&) = delete;
|
||||||
|
|
||||||
|
Vbo& getVbo(size_t index) const { return *m_relatedVbos.at(index); }
|
||||||
|
|
||||||
|
void bind() const;
|
||||||
|
void unbind() const;
|
||||||
|
|
||||||
|
void enableAttributes() const;
|
||||||
|
void disableAttributes(const std::vector<unsigned int>& attribNumbers) const;
|
||||||
|
|
||||||
|
Vbo& createDataFeed(size_t maxVertexCount, GLenum usage,
|
||||||
|
std::vector<std::unique_ptr<Attribute>> newAttributes);
|
||||||
|
|
||||||
|
Vbo& createInstanceDataFeed(size_t maxInstances,
|
||||||
|
std::vector<std::unique_ptr<Attribute>> newAttributes);
|
||||||
|
|
||||||
|
Vbo& initDataFeed(const void* data, size_t sizeInBytes, GLenum usage,
|
||||||
|
std::vector<std::unique_ptr<Attribute>> newAttributes);
|
||||||
|
|
||||||
|
void linkBoundVbo(std::unique_ptr<Vbo> vbo,
|
||||||
|
std::vector<std::unique_ptr<Attribute>> newAttributes);
|
||||||
|
|
||||||
|
void linkInstancingVbo(std::unique_ptr<Vbo> vbo,
|
||||||
|
std::vector<std::unique_ptr<Attribute>> newAttributes);
|
||||||
|
|
||||||
|
Vbo& createIndexBuffer(const unsigned int* indices, size_t count);
|
||||||
|
Vbo& createIndexBufferFeed(size_t maxIndexCount);
|
||||||
|
|
||||||
|
unsigned int getId() const { return m_id; }
|
||||||
|
bool hasIndexBuffer() const { return m_indexBuffer != nullptr; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit Vao(unsigned int id);
|
||||||
|
|
||||||
|
unsigned int m_id;
|
||||||
|
std::vector<std::unique_ptr<Vbo>> m_relatedVbos;
|
||||||
|
std::unique_ptr<Vbo> m_indexBuffer;
|
||||||
|
std::vector<std::unique_ptr<Attribute>> m_attributes;
|
||||||
|
|
||||||
|
void indicateInstancedAttributes(const std::vector<std::unique_ptr<Attribute>>& attributes) const;
|
||||||
|
void linkAttributes(int bytesPerVertex, std::vector<std::unique_ptr<Attribute>>& newAttributes);
|
||||||
|
static int getVertexDataTotalBytes(const std::vector<std::unique_ptr<Attribute>>& attributes);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace engine
|
||||||
|
|
||||||
|
#endif //COLORRACE_VAO_H
|
||||||
92
engine/src/utils/openglWrapper/openglObjects/Vbo.cpp
Normal file
92
engine/src/utils/openglWrapper/openglObjects/Vbo.cpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 29.07.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Vbo.h"
|
||||||
|
|
||||||
|
namespace engine {
|
||||||
|
|
||||||
|
Vbo::Vbo(unsigned int id, GLenum type, GLenum usage)
|
||||||
|
: m_id(id), m_type(type), m_usage(usage) {
|
||||||
|
bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vbo::~Vbo() {
|
||||||
|
glDeleteBuffers(1, &m_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Vbo> Vbo::create(GLenum type, GLenum usage) {
|
||||||
|
unsigned int id;
|
||||||
|
glGenBuffers(1, &id);
|
||||||
|
// std::unique_ptr<Vbo>(new Vbo(...)), da Konstruktor privat ist und
|
||||||
|
// std::make_unique keinen Zugriff auf private Konstruktoren hat
|
||||||
|
return std::unique_ptr<Vbo>(new Vbo(id, type, usage));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Vbo> Vbo::createAndAllocate(GLenum type, GLenum usage, size_t sizeInBytes) {
|
||||||
|
auto vbo = create(type, usage);
|
||||||
|
vbo->allocateData(sizeInBytes);
|
||||||
|
return vbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vbo::bind() const {
|
||||||
|
glBindBuffer(m_type, m_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vbo::unbind() const {
|
||||||
|
glBindBuffer(m_type, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vbo::allocateData(size_t sizeInBytes) {
|
||||||
|
allocateData(sizeInBytes, m_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vbo::orphan() {
|
||||||
|
allocateData(m_sizeInBytes, m_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vbo::allocateData(size_t sizeInBytes, GLenum target) {
|
||||||
|
glBufferData(target, static_cast<GLsizeiptr>(sizeInBytes), nullptr, m_usage);
|
||||||
|
m_sizeInBytes = sizeInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vbo::storeData(size_t startInBytes, const void* data, size_t dataSizeInBytes) {
|
||||||
|
glBufferSubData(m_type, static_cast<GLintptr>(startInBytes),
|
||||||
|
static_cast<GLsizeiptr>(dataSizeInBytes), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vbo::allocateAndStoreData(const void* data, size_t sizeInBytes) {
|
||||||
|
glBufferData(m_type, static_cast<GLsizeiptr>(sizeInBytes), data, m_usage);
|
||||||
|
m_sizeInBytes = sizeInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Vbo> Vbo::createTempVbo(size_t dataSize) {
|
||||||
|
auto tempVbo = create(GL_COPY_WRITE_BUFFER, GL_STATIC_COPY); // TODO: GL_STREAM_COPY erwägen?
|
||||||
|
tempVbo->allocateData(dataSize);
|
||||||
|
return tempVbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vbo::copyContentsTo(Vbo& destination, size_t readStart, size_t writeStart, size_t dataSize) const {
|
||||||
|
glBindBuffer(GL_COPY_READ_BUFFER, m_id);
|
||||||
|
glBindBuffer(GL_COPY_WRITE_BUFFER, destination.m_id);
|
||||||
|
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER,
|
||||||
|
static_cast<GLintptr>(readStart), static_cast<GLintptr>(writeStart),
|
||||||
|
static_cast<GLsizeiptr>(dataSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vbo::resize(size_t copyDataSize, size_t newSizeInBytes) {
|
||||||
|
if (copyDataSize == 0) {
|
||||||
|
bind();
|
||||||
|
allocateData(newSizeInBytes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto temporaryVbo = createTempVbo(copyDataSize);
|
||||||
|
copyContentsTo(*temporaryVbo, 0, 0, copyDataSize);
|
||||||
|
allocateData(newSizeInBytes, GL_COPY_READ_BUFFER);
|
||||||
|
temporaryVbo->copyContentsTo(*this, 0, 0, copyDataSize);
|
||||||
|
// temporaryVbo wird hier automatisch gelöscht (unique_ptr out-of-scope) -
|
||||||
|
// kein manuelles delete() nötig, im Gegensatz zur Java-Vorlage
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace engine
|
||||||
58
engine/src/utils/openglWrapper/openglObjects/Vbo.h
Normal file
58
engine/src/utils/openglWrapper/openglObjects/Vbo.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 29.07.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COLORRACE_VBO_H
|
||||||
|
#define COLORRACE_VBO_H
|
||||||
|
#pragma once
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace engine {
|
||||||
|
class Vbo {
|
||||||
|
public:
|
||||||
|
static std::unique_ptr<Vbo> create(GLenum type, GLenum usage);
|
||||||
|
static std::unique_ptr<Vbo> createAndAllocate(GLenum type, GLenum usage, size_t sizeInBytes);
|
||||||
|
|
||||||
|
~Vbo();
|
||||||
|
|
||||||
|
Vbo(const Vbo&) = delete;
|
||||||
|
Vbo& operator=(const Vbo&) = delete;
|
||||||
|
|
||||||
|
[[nodiscard]] size_t getByteSize() const { return m_sizeInBytes; }
|
||||||
|
[[nodiscard]] unsigned int getId() const { return m_id; }
|
||||||
|
|
||||||
|
void bind() const;
|
||||||
|
void unbind() const;
|
||||||
|
|
||||||
|
|
||||||
|
// Legt den Buffer neu an; kopiert optional vorhandene Daten in den neuen, größeren/kleineren Buffer
|
||||||
|
void resize(size_t copyDataSize, size_t newSizeInBytes);
|
||||||
|
|
||||||
|
void copyContentsTo(Vbo& destination, size_t readStart, size_t writeStart, size_t dataSize) const;
|
||||||
|
|
||||||
|
void allocateData(size_t sizeInBytes);
|
||||||
|
void allocateData(size_t sizeInBytes, GLenum target);
|
||||||
|
void orphan();
|
||||||
|
|
||||||
|
void storeData(size_t startInBytes, const void* data, size_t dataSizeInBytes);
|
||||||
|
void allocateAndStoreData(const void* data, size_t sizeInBytes);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vbo(unsigned int id, GLenum type, GLenum usage);
|
||||||
|
|
||||||
|
unsigned int m_id;
|
||||||
|
GLenum m_type;
|
||||||
|
GLenum m_usage;
|
||||||
|
size_t m_sizeInBytes = 0;
|
||||||
|
|
||||||
|
static std::unique_ptr<Vbo> createTempVbo(size_t dataSize);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //COLORRACE_VBO_H
|
||||||
Loading…
Reference in New Issue
Block a user