diff --git a/include/JGL/types/Texture.h b/include/JGL/types/Texture.h index b672d51..b95daca 100644 --- a/include/JGL/types/Texture.h +++ b/include/JGL/types/Texture.h @@ -34,13 +34,13 @@ namespace JGL { TextureWrappingMode texture_wrapping_mode; void load(SoftwareTexture* software_texture, const Vector2& size, const TextureFormat& format, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode); public: - ///Load a texture from a file, + Texture() = default; + /// Load a texture from a file, explicit Texture(const std::string& file, TextureFilteringMode filtering_mode = TextureFilteringMode::BILINEAR, TextureWrappingMode wrapping_mode = TextureWrappingMode::CLAMP_TO_EDGE); Texture(const std::string& file, const TextureFlag& flags, TextureFilteringMode filtering_mode = TextureFilteringMode::BILINEAR, TextureWrappingMode wrapping_mode = TextureWrappingMode::CLAMP_TO_EDGE); /* Initialize a texture filled with trash data this is primarily for the RenderTarget */ explicit Texture(const Vector2& size); - Texture() = default; public: [[nodiscard]] GLuint GetGLTextureHandle() const; [[nodiscard]] Vector2 GetDimensions() const; diff --git a/include/JGL/types/VRamList.h b/include/JGL/types/VRamList.h index ce0e83f..1e63eef 100644 --- a/include/JGL/types/VRamList.h +++ b/include/JGL/types/VRamList.h @@ -1,72 +1,64 @@ #pragma once +#include #include #include +#include #include #include -#include -#include -#include -#include -#include namespace JGL { class VRamList; } -/// A wrapper for VBO, Storing texture coordinates or vertices or indices in vram. +/// A wrapped for "Vertex Buffer Object" In OpenGL, Store things in VRam. class JGL::VRamList { private: GLuint list_handle = 0; - long size = 0; + long num_elements = 0; bool element_array_buffer = false; - void load(const GLfloat* data, const long& size); void load(const GLuint* data, const long& size); + void SetData(void* data, const long& length); + void UpdateData(void* data, const long& offset, const long& length); public: VRamList() = default; - VRamList(const GLuint* data, const long& size); - VRamList(const GLfloat* data, const long& size); - VRamList(Vector2* data, const long& size); - VRamList(Vector3* data, const long& size); - VRamList(Vector4* data, const long& size); + VRamList(const GLuint* data, const long& length); + VRamList(const GLfloat* data, const long& length); + VRamList(Vector2* data, const long& length); + VRamList(Vector3* data, const long& length); + VRamList(Vector4* data, const long& length); public: [[nodiscard]] GLuint GetHandle() const; - /// Returns the number of GLfloat or GLuint in the list. - [[nodiscard]] long GetSize() const; + /// Returns the number of elements in the list. + [[nodiscard]] long GetLength() const; /// Returns the size of the data in bytes. - [[nodiscard]] long GetDataSize() const; - [[nodiscard]] bool IsIntegerArray() const; + [[nodiscard]] size_t GetSize() const; + /** Get VBO data back from the GPU. This is *bad* because the CPU is going to wait + * for the transfer to finish. Has limited use other than testing. */ + [[nodiscard]] std::vector GetDataF() const; + [[nodiscard]] std::vector GetDataUI() const; [[nodiscard]] bool IsFloatArray() const; + /// Deallocate the vram the vbo took up. void Erase(); + /** Replace the data of an existing VBO in it's entirety. Must be same type. + * "length" refers to the number of elements in data. Not the number of bytes. */ + void SetData(const GLfloat* data, const long& length); + void SetData(const Vector2* data, const long& length); + void SetData(const Vector3* data, const long& length); + void SetData(const Vector4* data, const long& length); - /// Update the data of an existing VBO. Data would be the same type as the list already is. - /// "size" refers to the number of elements in data. Not the number of bytes. - void SetData(void* data, const long& size); + void SetData(const GLuint* data, const long& length); + void SetData(const Vector2i* data, const long& length); - /* Get VBO data back from the GPU. This is *very* slow because the CPU is going to wait - for the transfer to finish. I don't know why you'd want to do this outside of testing reasons.*/ - template - [[nodiscard]] std::vector GetData() const { - GLenum buffer_type; - GLint current_buffer = 0; - if constexpr (std::is_same::value) - buffer_type = GL_ARRAY_BUFFER, - glGetIntegerv(GL_ARRAY_BUFFER_BINDING, ¤t_buffer); - else if constexpr (std::is_same::value) - buffer_type = GL_ELEMENT_ARRAY_BUFFER, - glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, ¤t_buffer); - else - jlog::Fatal("Typename T must be either GLfloat or GLuint."); + /** Update only a portion of the data in a VBO. Must be same type. + * "length" refers to the number of elements in data. Not the number of bytes. + * "offset" refers the number of Typename T into the buffer the data you want to change is. + * For ex, offset 0 and length of 1 overwrites the first value. Offset 1 the second etc */ + void UpdateData(const GLfloat* data, const long& offset, const long& length); + void UpdateData(const Vector2* data, const long& offset, const long& length); + void UpdateData(const Vector3* data, const long& offset, const long& length); + void UpdateData(const Vector4* data, const long& offset, const long& length); - if ((element_array_buffer && buffer_type == GL_ARRAY_BUFFER) || (!element_array_buffer && buffer_type == GL_ELEMENT_ARRAY_BUFFER)) - jlog::Fatal("Returning the contents of a VRamList using the incorrect Typename T?"); - - glBindBuffer(buffer_type, list_handle); - std::vector data(size); - memcpy(data.data(), glMapBuffer(buffer_type, GL_READ_ONLY), size * sizeof(T)); - glUnmapBuffer(buffer_type); - glBindBuffer(buffer_type, current_buffer); - - return data; - } + void UpdateData(const GLuint* data, const long& offset, const long& length); + void UpdateData(const Vector2i* data, const long& offset, const long& length); }; \ No newline at end of file diff --git a/src/types/VRamList.cpp b/src/types/VRamList.cpp index 955930b..31871e0 100644 --- a/src/types/VRamList.cpp +++ b/src/types/VRamList.cpp @@ -1,52 +1,32 @@ #include -#include +#include #include -void JGL::VRamList::load(const GLfloat* data, const long& s) { +void JGL::VRamList::load(const GLfloat* data, const long& size) { GLint current_array_buffer = 0; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, ¤t_array_buffer); glGenBuffers(1, &list_handle); glBindBuffer(GL_ARRAY_BUFFER, list_handle); - glBufferData(GL_ARRAY_BUFFER, s, data, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, current_array_buffer); element_array_buffer = false; - size = s / sizeof(GLfloat); + num_elements = size / sizeof(GLfloat); } -void JGL::VRamList::load(const GLuint* data, const long& s) { +void JGL::VRamList::load(const GLuint* data, const long& size) { GLint current_element_array_buffer = 0; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, ¤t_element_array_buffer); glGenBuffers(1, &list_handle); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, list_handle); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, s, data, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, current_element_array_buffer); element_array_buffer = true; - size = s / sizeof(GLuint); -} - -JGL::VRamList::VRamList(const GLfloat* data, const long& size) { - load(data, (long) sizeof(GLfloat) * size); -} - -JGL::VRamList::VRamList(const GLuint* data, const long& size) { - load(data, (long) sizeof(GLuint) * size); -} - -JGL::VRamList::VRamList(Vector2* data, const long& size) { - load(reinterpret_cast(data), (long) sizeof(Vector2) * size); -} - -JGL::VRamList::VRamList(Vector3* data, const long& size) { - load(reinterpret_cast(data), (long) sizeof(Vector3) * size); -} - -JGL::VRamList::VRamList(Vector4* data, const long& size) { - load(reinterpret_cast(data), (long) sizeof(Vector4) * size); + num_elements = size / sizeof(GLuint); } void JGL::VRamList::Erase() { if (list_handle == 0) - jlog::Warning("Erasing an uninitialized array buffer?"); + JGL::Logger::Fatal("Erasing an uninitialized VRamList?"); GLint current_element_array_buffer = 0; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, ¤t_element_array_buffer); @@ -54,10 +34,10 @@ void JGL::VRamList::Erase() { glGetIntegerv(GL_ARRAY_BUFFER_BINDING, ¤t_array_buffer); if (element_array_buffer && current_element_array_buffer == list_handle) - jlog::Warning("Erasing an element array buffer while it's in use?"); + JGL::Logger::Warning("Erasing an element array buffer while it's in use?"); else if (!element_array_buffer && current_array_buffer == list_handle) - jlog::Warning("Erasing an array buffer while it's in use?"); + JGL::Logger::Warning("Erasing an array buffer while it's in use?"); glDeleteBuffers(1, &list_handle); } @@ -66,35 +46,31 @@ GLuint JGL::VRamList::GetHandle() const { return list_handle; } -bool JGL::VRamList::IsIntegerArray() const { - return element_array_buffer; -} - bool JGL::VRamList::IsFloatArray() const { return !element_array_buffer; } -long JGL::VRamList::GetSize() const { - return size; +long JGL::VRamList::GetLength() const { + return num_elements; } -long JGL::VRamList::GetDataSize() const { +size_t JGL::VRamList::GetSize() const { if (element_array_buffer) - return (long) sizeof(GLuint) * size; - return (long) sizeof(GLfloat) * size; + return sizeof(GLuint) * num_elements; + return sizeof(GLfloat) * num_elements; } -void JGL::VRamList::SetData(void* data, const long& size) { - bool should_resize = (this->size != size); +void JGL::VRamList::SetData(void* data, const long& length) { + bool should_resize = (this->num_elements != length); if (should_resize) { glDeleteBuffers(1, &list_handle); list_handle = 0; if (!element_array_buffer) - load((GLfloat*) data, sizeof(GLfloat) * size); + load((GLfloat*) data, sizeof(GLfloat) * length); else - load((GLuint*) data, sizeof(GLuint) * size); + load((GLuint*) data, sizeof(GLuint) * length); return; } @@ -108,13 +84,169 @@ void JGL::VRamList::SetData(void* data, const long& size) { glGetIntegerv(buffer_binding, ¤t_buffer); glBindBuffer(buffer_type, list_handle); - void* buffer_data = glMapBuffer(buffer_type, GL_WRITE_ONLY); - if (buffer_data == nullptr) - jlog::Fatal("Mapping in a VBO that doesn't exist?"); + void* vram = glMapBuffer(buffer_type, GL_WRITE_ONLY); + if (!vram) + JGL::Logger::Fatal("Mapping in a VBO that doesn't exist?"); - memcpy(buffer_data, data, (element_array_buffer ? sizeof(GLuint) : sizeof(GLfloat)) * size); + memcpy(vram, data, (element_array_buffer ? sizeof(GLuint) : sizeof(GLfloat)) * length); + if (!glUnmapBuffer(buffer_type)) - jlog::Fatal("We couldn't unmap the buffer?"); + JGL::Logger::Fatal("We couldn't unmap the buffer?"); glBindBuffer(buffer_type, current_buffer); } + +void JGL::VRamList::UpdateData(void* data, const long& offset, const long& length) { + + if (offset + length > num_elements) { + JGL::Logger::Warning("Using UpdateData to out-of-bounds write the VRamList? I'll resize it for you, But this is slow."); + unsigned long oob_delta = (offset + length) - num_elements; + + if (element_array_buffer) { + auto list_data = GetDataUI(); + list_data.resize(list_data.size() + oob_delta); + memcpy(list_data.data() + (offset * sizeof(GLuint)), data, length * sizeof(GLuint)); + SetData(list_data.data(), list_data.size()); + } + else { + auto list_data = GetDataF(); + list_data.resize(list_data.size() + oob_delta); + memcpy(list_data.data() + (offset * sizeof(GLfloat)), data, length * sizeof(GLfloat)); + SetData(list_data.data(), list_data.size()); + } + } + + GLint current_buffer = 0; + GLenum buffer_type = GL_ARRAY_BUFFER; + GLenum buffer_binding = GL_ARRAY_BUFFER_BINDING; + + if (element_array_buffer) + buffer_type = GL_ELEMENT_ARRAY_BUFFER, + buffer_binding = GL_ELEMENT_ARRAY_BUFFER_BINDING; + + glGetIntegerv(buffer_binding, ¤t_buffer); + glBindBuffer(buffer_type, list_handle); + + void* vram = glMapBuffer(buffer_type, GL_WRITE_ONLY); + if (!vram) + JGL::Logger::Fatal("Mapping in a VBO that doesn't exist?"); + + size_t element_size = element_array_buffer ? sizeof(GLuint) : sizeof(GLfloat); + memcpy(reinterpret_cast(reinterpret_cast(vram) + (offset * element_size)), data, length * element_size); + + if (!glUnmapBuffer(buffer_type)) + JGL::Logger::Fatal("We couldn't unmap the buffer?"); + + glBindBuffer(buffer_type, current_buffer); +} + +std::vector JGL::VRamList::GetDataF() const { + if (element_array_buffer) + JGL::Logger::Warning("Getting data as GLfloat but the buffer data is GLuint?"); + + GLint current_buffer = 0; + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, ¤t_buffer); + glBindBuffer(GL_ARRAY_BUFFER, list_handle); + + std::vector data(num_elements); + void* vram = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); + if (vram == nullptr) + JGL::Logger::Fatal("Mapping in a VBO that doesn't exist?"); + + memcpy(data.data(), vram, num_elements * sizeof(GLfloat)); + + glUnmapBuffer(GL_ARRAY_BUFFER); + glBindBuffer(GL_ARRAY_BUFFER, current_buffer); + + return data; +} + +std::vector JGL::VRamList::GetDataUI() const { + if (!element_array_buffer) + JGL::Logger::Warning("Getting data as GLuint but the buffer data is GLfloat?"); + + GLint current_buffer = 0; + glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, ¤t_buffer); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, list_handle); + std::vector data(num_elements); + + void* vram = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY); + if (vram == nullptr) + JGL::Logger::Fatal("Mapping in a VBO that doesn't exist?"); + + memcpy(data.data(), vram, num_elements * sizeof(GLuint)); + + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, current_buffer); + + return data; +} + +JGL::VRamList::VRamList(const GLfloat* data, const long& length) { + load(data, (long) sizeof(GLfloat) * length); +} + +JGL::VRamList::VRamList(const GLuint* data, const long& length) { + load(data, (long) sizeof(GLuint) * length); +} + +JGL::VRamList::VRamList(Vector2* data, const long& length) { + load(reinterpret_cast(data), (long) sizeof(Vector2) * length); +} + +JGL::VRamList::VRamList(Vector3* data, const long& length) { + load(reinterpret_cast(data), (long) sizeof(Vector3) * length); +} + +JGL::VRamList::VRamList(Vector4* data, const long& length) { + load(reinterpret_cast(data), (long) sizeof(Vector4) * length); +} + +void JGL::VRamList::SetData(const GLfloat* data, const long& length) { + SetData((void*) data, length); +} + +void JGL::VRamList::SetData(const Vector2* data, const long& length) { + SetData((void*) data, length * 2); +} + +void JGL::VRamList::SetData(const Vector3* data, const long& length) { + SetData((void*) data, length * 3); +} + +void JGL::VRamList::SetData(const Vector4* data, const long& length) { + SetData((void*) data, length * 4); +} + +void JGL::VRamList::SetData(const GLuint* data, const long& length) { + SetData((void*) data, length); +} + +void JGL::VRamList::SetData(const Vector2i* data, const long& length) { + SetData((void*) data, length * 2); +} + +void JGL::VRamList::UpdateData(const GLfloat* data, const long& offset, const long& length) { + UpdateData((void*) data, offset, length); +} + +void JGL::VRamList::UpdateData(const Vector2* data, const long& offset, const long& length) { + UpdateData((void*) data, offset, length * 2); +} + +void JGL::VRamList::UpdateData(const Vector3* data, const long& offset, const long& length) { + UpdateData((void*) data, offset, length * 3); +} + +void JGL::VRamList::UpdateData(const Vector4* data, const long& offset, const long& length) { + UpdateData((void*) data, offset, length * 4); +} + +void JGL::VRamList::UpdateData(const GLuint* data, const long& offset, const long& length) { + UpdateData((void*) data, offset, length); +} + +void JGL::VRamList::UpdateData(const Vector2i* data, const long& offset, const long& length) { + UpdateData((void*) data, offset, length * 2); +}