Heavy buffer update, window update, object tracking

This commit is contained in:
NaifBanana
2026-10-11 13:32:47 -05:00
parent e76ef32c45
commit 06f261b793
16 changed files with 553 additions and 843 deletions
@@ -57,7 +57,8 @@ class BufferError : public Error<BufferError> {
enum Codes : unsigned int {
UNDEFINED,
DATA_OVERFLOW,
DATA_ERROR
DATA_ERROR,
BAD_DATA_TYPE
};
static const std::string type;
static const ErrorCodeMap ErrorMessages;
@@ -69,7 +70,6 @@ class Buffer : public OpenGLObject {
using OpenGLObject::_id;
GLenum _usage = GL_STATIC_DRAW;
size_t _size;
Buffer(GLenum target) : Target(target) {}
virtual GLuint declare() override {
if (!_id) {
OPENGL_CALL(glGenBuffers(1, &_id));
@@ -88,6 +88,8 @@ class Buffer : public OpenGLObject {
public:
const GLenum Target;
using OpenGLObject::OpenGLObject;
Buffer(GLenum target);
Buffer(GLenum target, const ByteVector&, GLenum usage=GL_STATIC_DRAW);
Buffer(Buffer&& other);
Buffer& operator=(Buffer&& rhs);
@@ -151,15 +153,6 @@ protected:
}; */
class ArrayBuffer : public Buffer {
public:
template<typename T>
ArrayBuffer(const std::vector<T>& data, GLenum usage=GL_STATIC_DRAW)
: Buffer(GL_ARRAY_BUFFER) {
Buffer::data(vectorToBytes(data), usage);
}
};
class UniformBuffer : public Buffer {
protected:
GLuint _index;
@@ -172,58 +165,96 @@ class UniformBuffer : public Buffer {
};
class ElementBuffer : protected Buffer {
template<typename T>
struct IsValidGLElementIndexType {
static constexpr bool value = false;
};
template<typename T>
struct ValidGLElementIndexType {
static constexpr bool value = true;
static constexpr GLenum glsltype = GLSLType<T>::value;
};
template<>
struct IsValidGLElementIndexType<uint8_t> : public ValidGLElementIndexType<uint8_t> {};
template<>
struct IsValidGLElementIndexType<uint16_t> : public ValidGLElementIndexType<uint16_t> {};
template<>
struct IsValidGLElementIndexType<uint32_t> : public ValidGLElementIndexType<uint32_t> {};
class ElementBuffer : Buffer {
private:
template<typename T>
inline void checkForElementDataType() {
static_assert(IsValidGLElementIndexType<T>::value,
"ElementBuffer data type must resolve to one of GL_UNSIGNED_BYTE,"
"GL_UNSIGNED_SHORT, or GL_UNSIGNED_INT"
);
}
protected:
GLenum _glslType;
size_t _typeSize;
using Codes = BufferError::Codes;
using OpenGLObject::_id;
using Buffer::_usage;
using Buffer::_size;
using Buffer::declare;
using Buffer::remove;
GLenum _datatype;
template<typename T>
inline void checkDatatypeConsistency() {
if (_datatype != ValidGLElementIndexType<T>::value) {
THROW(BufferError(
Codes::BAD_DATA_TYPE,
GLenumTable[ValidGLElementIndexType<T>::value] + " not same as buffer "
"data type "+GLenumTable[_datatype]
));
}
}
public:
using Buffer::Target;
using Buffer::OpenGLObject;
using Buffer::bind;
using Buffer::usage;
using Buffer::unbind;
ElementBuffer();
using Buffer::usage;
using Buffer::size;
template<typename T>
ElementBuffer(const T* const data_ptr, size_t size, GLenum usage=GL_STATIC_DRAW)
: Buffer(GL_ELEMENT_ARRAY_BUFFER) {
data(data_ptr, size, usage);
}
template<typename T>
ElementBuffer(const std::vector<T>& data_, GLenum usage_=GL_STATIC_DRAW)
: ElementBuffer(data_.data(), data_.size(), usage_) {}
size_t size() const;
size_t typeSize() const;
ByteVector data() const;
GLenum glslType() const;
template<typename T>
void data(const T* data_, size_t size_, GLenum usage_=GL_STATIC_DRAW) {
declare();
using TypeInfo = GLSLType<T>;
_typeSize = TypeInfo::size;
Buffer::data(data_, size_*_typeSize, usage_);
_glslType = TypeInfo::value;
}
template<typename T>
void data(const std::vector<T>& data_, GLenum usage_=GL_STATIC_DRAW) {
data(data_.data(), data_.size(), usage_);
}
template<typename T>
void subdata(const T* data, size_t size, size_t offset) {
using TypeInfo = GLSLType<T>;
if ( _glslType != TypeInfo::value ) {
THROW( BufferError(
Codes::DATA_ERROR,
"Check element buffer data types"
) );
}
Buffer::subdata(data, size*_typeSize, offset);
}
template<typename T>
void subdata(const std::vector<T>& data, size_t offset=0) {
subdata(data.data(), data.size(), offset);
ElementBuffer(const std::vector<T>& indices, GLenum usage=GL_STATIC_DRAW) : Buffer(GL_ELEMENT_ARRAY_BUFFER) {
data(indices, usage);
}
inline GLenum datatype() { return _datatype; }
template<typename T>
void data(const std::vector<T>& data, GLenum usage=GL_STATIC_DRAW) {
checkForElementDataType<T>();
_datatype = ValidGLElementIndexType<T>::glsltype;
Buffer::data(vectorToBytes(data), usage);
}
template<typename T>
void data(const T* data, size_t size, GLenum usage=GL_STATIC_DRAW) {
checkForElementDataType<T>();
_datatype = ValidGLElementIndexType<T>::glsltype;
Buffer::data((void*)data, size * sizeof(T), usage);
}
template<typename T>
void subdata(const T* data, size_t size, GLintptr offset=0) {
checkForElementDataType<T>();
checkDatatypeConsistency<T>();
Buffer::subdata((void*)data, size * sizeof(T), offset);
}
template<typename T>
void subdata(const std::vector<T>& data_, GLintptr offset=0) {
checkForElementDataType<T>();
checkDatatypeConsistency<T>();
Buffer::subdata(vectorToBytes(data_), offset);
}
};
@@ -1,83 +0,0 @@
#pragma once
#ifndef _NB_DRAW
#define _NB_DRAW
#include <NBGraphics/GLLoad.hpp>
#include <exception>
#include <map>
#include <string>
#include <vector>
#include <NBGraphics/Buffers.hpp>
#include <NBGraphics/VertexArray.hpp>
#define THROW_DRAW_ERROR(msg) throw DrawError(msg, __FILE__, __LINE__);
namespace nb{
class DrawError : public std::runtime_error {
public:
DrawError(const std::string&, const std::string& file="", int line=-1);
};
uint8_t VerticesFromPrimitives(GLenum, unsigned int num_prims=1);
uint8_t PrimitivesFromVertices(GLenum, unsigned int);
void copyVertexAttribute(const VertexAttribute&, VertexAttribute&);
class DrawBuffer {
public:
typedef std::shared_ptr<Buffer> BufferManagerPointer;
DrawBuffer(VertexAttributeList, GLenum prim_type=GL_TRIANGLES);
//DrawBuffer(std::initializer_list<VertexAttribute>, std::initializer_list<VertexAttributePointer>);
unsigned int vertSize() const;
const std::shared_ptr<ShaderProgram> shader() const;
unsigned int elementBufferID() const;
unsigned int vertexBufferID() const;
virtual void draw() const;
RawVec vertAttrData(unsigned int);
VertexAttributeList changeVertLayout(unsigned int, VertexAttributePointer);
RawVec vertAttrData(unsigned int, const RawVec&);
virtual void elementData(const std::vector<unsigned int>&);
virtual void elementData(unsigned int);
virtual void elementData(const std::vector<unsigned int>&, unsigned int offset);
virtual void vertexData(const RawVec&);
virtual void vertexData(unsigned int num_verts);
virtual void vertexData(const RawVec&, unsigned int offset);
BufferManagerPointer _vert_data;
BufferManagerPointer _elmt_data;
VAOManager _VAO;
const GLenum _gl_primitive_type=0;
virtual VertexAttributeList defaultVAO(VertexAttributeList);
unsigned int _num_verts, _num_prims;
protected:
};
class DrawInstanceBuffer : public DrawBuffer {
public:
DrawInstanceBuffer(VertexAttributeList, VertexAttributeList, GLenum primt_type=GL_TRIANGLES);
unsigned int instSize() const;
unsigned int instanceBufferID() const;
virtual void draw() const override;
VertexAttributeList changeInstanceLayout(unsigned int, VertexAttributePointer);
virtual void instanceData(const RawVec&);
virtual void instanceData(unsigned int);
virtual void instanceData(const RawVec&, unsigned int offset);
BufferManagerPointer _inst_data;
virtual VertexAttributeList defaultVAO(VertexAttributeList);
unsigned int _num_inst;
protected:
};
}
#endif
@@ -0,0 +1,81 @@
#pragma once
#ifndef _NB_MESH
#define _NB_MESH
#include <NBGraphics/GLLoad.hpp>
#include <NBGraphics/Buffers.hpp>
#include <NBGraphics/VertexArray.hpp>
#include <NBGraphics/VertexData.hpp>
namespace nb{
class Mesh {
protected:
const GLenum _primitive;
const unsigned int _count;
std::shared_ptr<VAO> _vao;
public:
Mesh(
VertexDataPointerList vao,
unsigned int count,
GLenum primitive=GL_TRIANGLES
);
Mesh(GLenum primitive, const std::shared_ptr<VAO>& vertex_array, unsigned int count);
Mesh(GLenum primitive, const VertexData& vertex_data, unsigned int count);
Mesh(
GLenum primitive,
const ByteVector& data,
unsigned int count,
const std::vector<VertexAttribute>& attributes
);
Mesh(Mesh&&);
Mesh(const Mesh&&) = delete;
Mesh& operator=(Mesh&&) = delete;
Mesh& operator=(const Mesh&) = delete;
inline virtual void draw() const { this->draw(_count); }
inline virtual void draw(unsigned int count) const { this->draw(0, count); }
virtual void draw(unsigned int offset, unsigned int count) const;
inline GLenum primitive() const { return _primitive; }
inline unsigned int count() const { return _count; }
inline std::shared_ptr<VAO> vao() const { return _vao; }
};
class InstancedMesh : public Mesh {
protected:
using Mesh::_primitive;
using Mesh::_count;
using Mesh::_vao;
public:
virtual void draw(unsigned int offset, unsigned int count) const;
};
class IndexedMesh : public Mesh {
protected:
std::shared_ptr<ElementBuffer> _ebo;
public:
template<typename T>
IndexedMesh(
GLenum primitive,
const ByteVector& data,
const std::vector<VertexAttribute>& attributes,
const std::vector<T>& indices
) : Mesh(primitive, data, indices.size(), attributes) {
_vao->bind();
_ebo = std::make_shared<ElementBuffer>(indices);
}
using Mesh::draw;
virtual void draw(unsigned int offset, unsigned int count) const;
};
class InstancedIndexedMesh : virtual public IndexedMesh {};
}
#endif
@@ -11,6 +11,7 @@ namespace nb {
typedef ConstantMap<GLenum, std::string> GLEnumTableType;
extern const GLEnumTableType GLenumTable;
extern const ConstantMap<TypeCodes, GLint> TypeToGLSL;
class OpenGLError : public Error<OpenGLError> {
using Base = Error<OpenGLError>;
@@ -8,6 +8,7 @@
#include <NBGraphics/Buffers.hpp>
#include <NBGraphics/OGLObjects.hpp>
#include <NBGraphics/VertexData.hpp>
namespace nb {
@@ -33,32 +34,13 @@ static uint8_t GLSLTypeSize(GLenum type) {
}
}
struct VertexAttributeLayout {
int32_t offset = 0;
GLsizei stride = 0;
GLuint divisor = 0;
};
struct VertexAttribute {
GLint GLSLSize;
GLenum GLSLType;
GLboolean GLSLNormalization;
VertexAttributeLayout layout;
};
struct VertexAttributePointer {
VertexAttribute attribute;
GLuint buffer;
GLuint index;
};
static bool isIndexInVertexAttribute(int i, const VertexAttribute& va) {
if ((i -= va.layout.offset) < 0) { return false; }
return (i%va.layout.stride) < GLSLTypeSize(va.GLSLType) * va.GLSLSize;
return (i%va.layout.stride) < GLSLTypeSize(TypeToGLSL[va.type]) * va.size;
}
typedef std::vector<VertexAttribute> VertexAttributeList;
typedef std::vector<VertexAttributePointer> VertexAttributePointerList;
typedef std::vector<VertexData> VertexDataList;
typedef std::vector<VertexDataPointer> VertexDataPointerList;
class VAOError : public Error<VAOError> {
using Base = Error<VAOError>;
@@ -78,10 +60,30 @@ class VAO : public OpenGLObject {
using Base = OpenGLObject;
using Codes = VAOError::Codes;
protected:
using Base::_id;
VertexDataPointerList _vertexdata;
virtual void remove() override {
if(_id) {
disable();
bind();
OPENGL_CALL(glDeleteVertexArrays(1, &_id));
_id = 0;
}
}
virtual GLuint declare() override {
if (!_id) {
OPENGL_CALL(glGenVertexArrays(1, &_id));
}
bind();
return _id;
}
public:
using Base::Base;
VAO() = default;
VAO(const VertexAttributePointerList&);
VAO(const VertexDataPointerList&);
VAO(VAO&&);
VAO& operator=(VAO&&);
@@ -100,34 +102,15 @@ class VAO : public OpenGLObject {
OPENGL_CALL(glBindVertexArray(0));
}
VertexAttributePointerList attributes() const;
VertexAttributePointerList attributes(const VertexAttributePointerList&);
VertexAttributePointer attr(GLuint) const;
VertexDataPointerList attributes() const;
VertexDataPointerList attributes(const VertexDataPointerList&);
VertexDataPointerList attributes(const VertexDataList&);
VertexDataPointer attribute(GLuint) const;
void enable() const;
void enable(GLuint) const;
void disable() const;
void disable(GLuint) const;
protected:
using Base::_id;
VertexAttributePointerList _attrs;
virtual void remove() override {
if(_id) {
disable();
bind();
OPENGL_CALL(glDeleteVertexArrays(1, &_id));
_id = 0;
}
}
virtual GLuint declare() override {
if (!_id) {
OPENGL_CALL(glGenVertexArrays(1, &_id));
}
bind();
return _id;
}
};
class VertexError : public Error<VertexError> {
@@ -144,97 +127,5 @@ class VertexError : public Error<VertexError> {
};
using VBO = ArrayBuffer;
using VertBufVec = SharedVector<VBO>;
using EBO = ElementBuffer;
struct VertexData {
std::shared_ptr<VBO> vbo;
VertexAttributeList attrs;
};
using VertexDataVec = std::vector<VertexData>;
class VertexGroup {
protected:
using Codes = VertexError::Codes;
VertexDataVec _vertex_data;
std::shared_ptr<EBO> _ebo;
std::shared_ptr<VAO> _vao;
GLenum _primitive;
public:
GLenum primitive=GL_TRIANGLES;
VertexGroup(VertexGroup&&);
VertexGroup& operator=(VertexGroup&&);
VertexGroup(
const VertexDataVec& vertex_data,
const std::shared_ptr<EBO>& ebo
)
: _vao(std::make_shared<VAO>()), _ebo(ebo) {
setBuffers(vertex_data);
}
template<typename... T>
VertexGroup(
const VertexDataVec& vertex_data,
T... args
)
: VertexGroup(vertex_data, std::make_shared<EBO>(args...)) {
setBuffers(vertex_data);
}
template<typename... T>
VertexGroup(
const VertexData& vertex_data,
T... args
)
: VertexGroup(VertexDataVec{vertex_data}, args...) {}
template<typename... T>
VertexGroup(
const ByteVector& vertex_data,
const VertexAttributeList& vertex_specification,
T... args
) : VertexGroup({
std::make_shared<VBO>(vertex_data),
vertex_specification},
args...
) {}
void bind() const {
_vao->bind();
_ebo->bind();
}
void unbind() const {
_vao->unbind();
_ebo->unbind();
}
void draw() const;
VertexDataVec getBuffers();
VertexData getBuffers(size_t);
size_t setBuffers(const VertexDataVec&);
size_t addBuffer(const VertexData&);
size_t addBuffer(const ByteVector& data, const VertexAttributeList& attrs);
VertexDataVec dropBuffers();
VertexData dropBuffer(size_t);
VertexAttributePointer attribute(size_t) const;
void enableAttr(GLuint);
void disableAttr(GLuint);
void enableBuffer(size_t);
void disableBuffer(size_t);
void enable();
void disable();
std::shared_ptr<EBO> indices() const;
std::shared_ptr<EBO> indices(const std::vector<unsigned int>& data);
std::shared_ptr<EBO> indices(std::shared_ptr<EBO> buffer);
};
} // namespace nb
#endif // _NB_VERTEX_ARRAY
@@ -0,0 +1,43 @@
#pragma once
#ifndef _NB_VERTEX_DATA
#define _NB_VERTEX_DATA
#include <memory>
#include <vector>
#include <NBCore/TypeTraits.hpp>
#include <NBCore/Utils.hpp>
#include <NBGraphics/Buffers.hpp>
#include <NBGraphics/GLLoad.hpp>
// #include <NBGraphics/VertexArray.hpp>
namespace nb {
struct VertexAtrributeLayout {
unsigned int offset = 0;
int stride = 0;
unsigned int divisor = 0;
};
struct VertexAttribute {
unsigned int size;
TypeCodes type;
bool normalized;
VertexAtrributeLayout layout;
};
struct VertexData {
std::shared_ptr<Buffer> data;
std::vector<VertexAttribute> attributes;
VertexData(std::shared_ptr<Buffer>, const std::vector<VertexAttribute>&);
VertexData(const ByteVector&, const std::vector<VertexAttribute>&);
};
struct VertexDataPointer {
std::shared_ptr<VertexData> vertexdata;
unsigned int index;
};
} // namespace nb
#endif
+39 -15
View File
@@ -42,32 +42,44 @@ class OGLWindow {
protected:
static std::atomic<unsigned int> _count;
static std::atomic<bool> _glfwInitialized;
static thread_local std::shared_ptr<OGLWindow> _currWindow;
static thread_local GLFWwindow* _currArena;
std::string _title;
GLFWwindow* _window_ptr;
GLFWwindow* _arena;
static thread_local GLFWwindow* _currWindow;
static thread_local const GLFWwindow* _currArena;
static void SetHintInteger(const std::array<int, 2>&);
static void SetHintString(const std::tuple<int, std::string>&);
std::string _title;
GLFWwindow* _window_ptr;
const GLFWwindow* _arena;
OGLWindow(
unsigned int,
unsigned int,
const std::string&,
const std::vector<std::array<int, 2>>&,
const std::vector<std::tuple<int, std::string>>&
const std::vector<std::tuple<int, std::string>>&,
GLFWwindow* sharingContext = NULL
);
GLFWwindow* makeCurrent() const;
void detachWindow();
public:
enum Callbacks {
KEY, CHAR, CHAR_MODS, MOUSE_BUTTON, CURSOR_POS, CURSOR_ENTER,
SCROLL, DROP, WINDOW_POS, WINDOW_SIZE, WINDOW_CLOSE, WINDOW_REFRESH,
WINDOW_FOCUS, WINDOW_ICONIFY, WINDOW_MAX, FRAMEBUFFER_SIZE, WINDOW_SCALE,
};
template<typename... T>
using CallbackFunc = void(*)(OGLWindow*, T...);
static inline bool IsGLFWInitialized() { return _glfwInitialized; }
static bool InitGLFW(const std::vector<GLFWHint>& hints={});
static bool TerminateGLFW();
static inline std::shared_ptr<OGLWindow> getCurrentWindow() { return _currWindow; }
static inline const GLFWwindow* getCurrentObjectArena() { return _currArena; }
static std::shared_ptr<OGLWindow> MakeCurrent(const std::shared_ptr<OGLWindow>&);
static inline std::shared_ptr<OGLWindow> DropCurrent() { return MakeCurrent(nullptr); }
static inline GLFWwindow* GetCurrentWindow() { return _currWindow; }
static inline const GLFWwindow* GetCurrentObjectArena() { return _currArena; }
static GLFWwindow* MakeCurrent(const std::shared_ptr<OGLWindow>&);
static inline GLFWwindow* DropCurrent() { return MakeCurrent(nullptr); }
static void DestroyWindow(std::shared_ptr<OGLWindow>&);
static std::shared_ptr<OGLWindow> CreateWindow(
unsigned int x,
unsigned int y,
@@ -75,21 +87,33 @@ class OGLWindow {
const std::vector<std::array<int, 2>>& integerHints={},
const std::vector<std::tuple<int, std::string>>& stringHints={}
);
static std::shared_ptr<OGLWindow> CreateSharedWindow(
unsigned int x,
unsigned int y,
const std::string& title,
std::shared_ptr<OGLWindow> sharingWindow,
const std::vector<std::array<int, 2>>& integerHints={},
const std::vector<std::tuple<int, std::string>>& stringHints={}
);
OGLWindow(OGLWindow&&) = delete;
OGLWindow(const OGLWindow&) = delete;
~OGLWindow();
inline bool operator==(const OGLWindow& rhs) { return _window_ptr==rhs._window_ptr; }
int getWindowAttribute(int) const;
inline GLFWwindow* getWindowPtr() const { return _window_ptr; }
inline const GLFWwindow* getObjectArena() const { return _arena; }
inline std::string getTitle() const { return _title; }
std::array<int, 2> getSize() const;
std::shared_ptr<OGLWindow> makeSharedContext();
bool shouldClose() const;
inline void processEvents() const { CheckForMainThread(); glfwPollEvents(); }
inline void refresh() const { glfwSwapBuffers(_window_ptr); }
void makeCurrent() const;
void setSize(unsigned int x, unsigned int y);
void setTitle(const std::string&);
void shouldClose(bool);
/* template<enum Callbacks, typename Func>
void setCallBack(Func); */
};
};