Huge graphics overhaul
This commit is contained in:
@@ -12,15 +12,92 @@ const std::string BufferError::type = "nb::BufferError";
|
||||
const ErrorCodeMap BufferError::ErrorMessages = {
|
||||
{ BufferErrorCodes::UNDEFINED, "Error" },
|
||||
{ BufferErrorCodes::DATA_OVERFLOW, "Attempting buffer overflow" },
|
||||
{ BufferErrorCodes::INVALID_BUFFER, "Attempting operation on invalid buffer" },
|
||||
{ BufferErrorCodes::HANDLE_OVERWRITE, "Attempting to overwrite active buffer"}
|
||||
{BufferErrorCodes::DATA_ERROR, "Invalid memory operation"}
|
||||
|
||||
};
|
||||
|
||||
template<>
|
||||
ArrayBuffer<false>::ArrayBuffer(const ByteVector& data_, GLenum usage_)
|
||||
: BufferType() {
|
||||
data(data_, usage_);
|
||||
Buffer::Buffer(Buffer&& rval) : Target(rval.Target) {
|
||||
*this = std::move(rval);
|
||||
}
|
||||
|
||||
Buffer& Buffer::operator=(Buffer&& rhs) {
|
||||
if (Target != rhs.Target) {
|
||||
auto targ_name = BufferTypes.at(Target);
|
||||
THROW(OGLError(
|
||||
OGLError::Codes::INVALID_OBJECT,
|
||||
"w/ BufferType "+targ_name+" != BufferType "+BufferTypes.at(rhs.Target)
|
||||
));
|
||||
}
|
||||
OpenGLObject::operator=(std::move(rhs));
|
||||
_usage = rhs._usage;
|
||||
_size = rhs._size;
|
||||
|
||||
rhs._usage = GL_STATIC_DRAW;
|
||||
rhs._size = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
GLenum Buffer::usage() const { return _usage; }
|
||||
|
||||
size_t Buffer::size() const { return _size; }
|
||||
|
||||
ByteVector Buffer::data() const {
|
||||
bind();
|
||||
ByteVector ret(_size);
|
||||
glGetBufferSubData(Target, 0, _size, ret.data());
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Buffer::data(const void* data_, size_t size_, GLenum usage_) {
|
||||
declare();
|
||||
glBufferData(Target, size_, data_, usage_);
|
||||
_size = size_;
|
||||
_usage = usage_;
|
||||
}
|
||||
|
||||
void Buffer::data(const ByteVector& data_, GLenum usage_) {
|
||||
declare();
|
||||
data(data_.data(), data_.size(), usage_);
|
||||
}
|
||||
|
||||
void Buffer::subdata(const void* data_, size_t size_, GLintptr offset_) {
|
||||
bind();
|
||||
if (offset_+size_ <= _size) {
|
||||
THROW(BufferError(BufferError::Codes::DATA_OVERFLOW));
|
||||
}
|
||||
glBufferSubData(Target, offset_, size_, data_);
|
||||
}
|
||||
|
||||
void Buffer::subdata(const ByteVector& data_, GLintptr offset_) {
|
||||
bind();
|
||||
size_t size_ = data_.size();
|
||||
subdata(data_.data(), size_);
|
||||
}
|
||||
|
||||
ElementBuffer::ElementBuffer() : Buffer(GL_ELEMENT_ARRAY_BUFFER) {}
|
||||
|
||||
ByteVector ElementBuffer::data() const {
|
||||
return data();
|
||||
}
|
||||
|
||||
size_t ElementBuffer::size() const { return _size / _typeSize; }
|
||||
|
||||
size_t ElementBuffer::typeSize() const { return _typeSize; }
|
||||
|
||||
GLenum ElementBuffer::glslType() const { return _glslType; }
|
||||
|
||||
template void ElementBuffer::data<uint8_t>(const std::vector<uint8_t>& data, GLenum usage);
|
||||
template void ElementBuffer::data<uint16_t>(const std::vector<uint16_t>& data, GLenum usage);
|
||||
template void ElementBuffer::data<uint32_t>(const std::vector<uint32_t>& data, GLenum usage);
|
||||
template void ElementBuffer::data<uint8_t>(const uint8_t* const data, size_t size, GLenum usage);
|
||||
template void ElementBuffer::data<uint16_t>(const uint16_t* const data, size_t size, GLenum usage);
|
||||
template void ElementBuffer::data<uint32_t>(const uint32_t* const data, size_t size, GLenum usage);
|
||||
|
||||
template void ElementBuffer::subdata<uint8_t>(const uint8_t* const data, size_t size, size_t offset=0);
|
||||
template void ElementBuffer::subdata<uint16_t>(const uint16_t* const data, size_t size, size_t offset=0);
|
||||
template void ElementBuffer::subdata<uint32_t>(const uint32_t* const data, size_t size, size_t offset=0);
|
||||
template void ElementBuffer::subdata<uint8_t>(const std::vector<uint8_t>& data, size_t offset=0);
|
||||
template void ElementBuffer::subdata<uint16_t>(const std::vector<uint16_t>& data, size_t offset=0);
|
||||
template void ElementBuffer::subdata<uint32_t>(const std::vector<uint32_t>& data, size_t offset=0);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
#include "FrameBuffers.hpp"
|
||||
|
||||
namespace nb {
|
||||
|
||||
using FBOErrorCodes = FrameBufferError::Codes;
|
||||
const std::string FrameBufferError::type = "nb::FrameBufferError";
|
||||
const ErrorCodeMap FrameBufferError::ErrorMessages = {
|
||||
{FBOErrorCodes::UNDEFINED, "Error"},
|
||||
{FBOErrorCodes::INVALID_VALUE, "Invalid value"}
|
||||
};
|
||||
|
||||
GLuint FrameBufferBase::declare() {
|
||||
if (!_id) {
|
||||
glGenFramebuffers(1, &_id);
|
||||
}
|
||||
bind();
|
||||
return _id;
|
||||
}
|
||||
|
||||
void FrameBufferBase::remove() {
|
||||
if (_id) {
|
||||
unbind();
|
||||
glDeleteFramebuffers(1, &_id);
|
||||
_id=0;
|
||||
}
|
||||
}
|
||||
|
||||
FrameBufferBase::FrameBufferBase(GLenum target) : Target(target) {}
|
||||
|
||||
std::shared_ptr<RenderTarget> FrameBufferBase::detach(GLenum attch_) {
|
||||
bind();
|
||||
auto ret = _attachments.at(attch_);
|
||||
_attachments.erase(attch_);
|
||||
glFramebufferTexture(Target, attch_, 0, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FrameBufferBase::attach(
|
||||
GLenum attachment_,
|
||||
std::shared_ptr<Texture> texture_,
|
||||
unsigned int level_,
|
||||
unsigned int layer_
|
||||
) {
|
||||
declare();
|
||||
if (attachment_ == GL_NONE) {
|
||||
THROW(FrameBufferError(FrameBufferError::INVALID_VALUE,
|
||||
"Cannot attach object to `GL_NONE`"
|
||||
));
|
||||
}
|
||||
glFramebufferTextureLayer(
|
||||
Target,
|
||||
attachment_,
|
||||
texture_->id(),
|
||||
level_,
|
||||
layer_
|
||||
);
|
||||
_attachments[attachment_] = texture_;
|
||||
}
|
||||
|
||||
void FrameBufferBase::attach(
|
||||
GLenum attachment_,
|
||||
std::shared_ptr<Texture> texture_,
|
||||
unsigned int level_
|
||||
) {
|
||||
declare();
|
||||
if (attachment_ == GL_NONE) {
|
||||
THROW(FrameBufferError(FrameBufferError::INVALID_VALUE,
|
||||
"Cannot attach object to `GL_NONE`"
|
||||
));
|
||||
}
|
||||
if (texTypeIs2D(texture_->Target)) {
|
||||
glFramebufferTexture2D(
|
||||
Target,
|
||||
attachment_,
|
||||
texture_->Target,
|
||||
texture_->id(),
|
||||
level_
|
||||
);
|
||||
} else {
|
||||
glFramebufferTexture1D(
|
||||
Target,
|
||||
attachment_,
|
||||
texture_->Target,
|
||||
texture_->id(),
|
||||
level_
|
||||
);
|
||||
}
|
||||
_attachments[attachment_] = texture_;
|
||||
}
|
||||
|
||||
void FrameBufferBase::bind() const {
|
||||
if (_id) {
|
||||
glBindFramebuffer(Target, _id);
|
||||
} else {
|
||||
THROW(OGLError(
|
||||
OGLError::Codes::INVALID_OBJECT,
|
||||
"w/ FrameBuffer"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void FrameBufferBase::unbind() const {
|
||||
glBindFramebuffer(Target, 0);
|
||||
}
|
||||
|
||||
GLenum FrameBufferBase::status() const {
|
||||
bind();
|
||||
return glCheckFramebufferStatus(Target);
|
||||
}
|
||||
|
||||
FrameBufferBase::AttachmentMap FrameBufferBase::getAllBuffers() const {
|
||||
return _attachments;
|
||||
}
|
||||
|
||||
std::shared_ptr<RenderTarget> FrameBufferBase::getBuffer(GLenum attch_) const {
|
||||
try {
|
||||
return _attachments.at(attch_);
|
||||
} catch (const std::out_of_range& e) {
|
||||
THROW(e);
|
||||
}
|
||||
}
|
||||
|
||||
// class ReadFrameBuffer
|
||||
|
||||
ReadFrameBuffer::ReadFrameBuffer()
|
||||
: _location(GL_NONE), FrameBufferBase(GL_READ_FRAMEBUFFER) {}
|
||||
|
||||
ReadFrameBuffer& ReadFrameBuffer::operator=(WriteFrameBuffer&& mv) {
|
||||
if (mv.id()) {
|
||||
_attachments = mv.getAllBuffers();
|
||||
mv.setWriteBuffer(GL_NONE);
|
||||
mv._attachments = {};
|
||||
mv._locations = {};
|
||||
FrameBufferBase::OpenGLObject::operator=(std::move(mv));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ReadFrameBuffer& ReadFrameBuffer::operator=(ReadFrameBuffer&& mv) {
|
||||
if (mv.id()) {
|
||||
_attachments = mv._attachments;
|
||||
_location = mv._location;
|
||||
mv._attachments = {};
|
||||
mv._location = GL_NONE;
|
||||
FrameBufferBase::OpenGLObject::operator=(std::move(mv));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::shared_ptr<RenderTarget> ReadFrameBuffer::getReadBuffer() const {
|
||||
if (_location == GL_NONE) { return nullptr; }
|
||||
return getBuffer(_location);
|
||||
}
|
||||
|
||||
GLenum ReadFrameBuffer::getReadLocation() const { return _location; }
|
||||
|
||||
std::shared_ptr<RenderTarget> ReadFrameBuffer::setReadBuffer(GLenum attch_) {
|
||||
bind();
|
||||
if (attch_!=GL_NONE) {
|
||||
try {
|
||||
const auto& x = _attachments.at(attch_);
|
||||
} catch (const std::out_of_range& e) {
|
||||
THROW(FrameBufferError(FrameBufferError::INVALID_VALUE,
|
||||
"No buffer set at attachment"
|
||||
));
|
||||
}
|
||||
}
|
||||
_location = attch_;
|
||||
glReadBuffer(_location);
|
||||
return getReadBuffer();
|
||||
}
|
||||
|
||||
// class WriteFrameBuffer
|
||||
|
||||
WriteFrameBuffer::WriteFrameBuffer()
|
||||
: FrameBufferBase(GL_DRAW_FRAMEBUFFER) {}
|
||||
|
||||
WriteFrameBuffer& WriteFrameBuffer::operator=(ReadFrameBuffer&& rhs) {
|
||||
if (rhs.id()) {
|
||||
_attachments = rhs._attachments;
|
||||
rhs.setReadBuffer(GL_NONE);
|
||||
rhs._attachments = {};
|
||||
rhs._location = GL_NONE;
|
||||
FrameBufferBase::OpenGLObject::operator=(std::move(rhs));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
WriteFrameBuffer& WriteFrameBuffer::operator=(WriteFrameBuffer&& rhs) {
|
||||
if (rhs.id()) {
|
||||
_attachments = rhs._attachments;
|
||||
_locations = rhs._locations;
|
||||
rhs._attachments = {};
|
||||
rhs._locations = {};
|
||||
FrameBufferBase::OpenGLObject::operator=(std::move(rhs));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
using fRGBA = RGBA<float>;
|
||||
|
||||
std::vector<std::shared_ptr<Texture>> WriteFrameBuffer::getWriteBuffers() const {
|
||||
const size_t count = _locations.size();
|
||||
std::vector<std::shared_ptr<Texture>> ret(count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
ret[i] = std::static_pointer_cast<Texture>(getBuffer(_locations[i]));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<GLenum> WriteFrameBuffer::getWriteLocations() const {
|
||||
return _locations;
|
||||
}
|
||||
|
||||
WriteFrameBuffer::DrawTexVec WriteFrameBuffer::setWriteBuffers(const std::vector<GLenum>& attchs_) {
|
||||
bind();
|
||||
for (GLenum loc : attchs_) {
|
||||
if (getBuffer(loc)->Target == GL_RENDERBUFFER) {
|
||||
THROW(FrameBufferError(FrameBufferError::INVALID_VALUE,
|
||||
"Cannot write to renderbuffer [ @ Attachment = "+std::to_string(loc)+" ]"
|
||||
));
|
||||
}
|
||||
}
|
||||
_locations = attchs_;
|
||||
glDrawBuffers(_locations.size(), _locations.data());
|
||||
return getWriteBuffers();
|
||||
}
|
||||
|
||||
std::shared_ptr<Texture> WriteFrameBuffer::setWriteBuffer(GLenum attch_) {
|
||||
bind();
|
||||
if (attch_ == GL_NONE) {
|
||||
std::vector<GLenum> tmp(_locations.size(), GL_NONE);
|
||||
glDrawBuffers(tmp.size(), tmp.data());
|
||||
_locations = {};
|
||||
return nullptr;
|
||||
}
|
||||
setWriteBuffers({attch_});
|
||||
return std::static_pointer_cast<Texture>(getBuffer(attch_));
|
||||
}
|
||||
|
||||
fRGBA WriteFrameBuffer::clearColorValue() const {
|
||||
bind();
|
||||
float rgba[4];
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
|
||||
return fRGBA{rgba[0], rgba[1], rgba[2], rgba[3]};
|
||||
}
|
||||
|
||||
fRGBA WriteFrameBuffer::clearColorValue(const fRGBA& color) {
|
||||
declare();
|
||||
glClearColor(color.r, color.g, color.b, color.a);
|
||||
return color;
|
||||
}
|
||||
|
||||
fRGBA WriteFrameBuffer::clearColorValue(float r, float g, float b, float a) {
|
||||
return clearColorValue({r, g,b , a});
|
||||
}
|
||||
|
||||
double WriteFrameBuffer::clearDepthValue() const {
|
||||
bind();
|
||||
double ret;
|
||||
glGetDoublev(GL_DEPTH_CLEAR_VALUE, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
double WriteFrameBuffer::clearDepthValue(double d_) {
|
||||
declare();
|
||||
glClearDepth(d_);
|
||||
return d_;
|
||||
}
|
||||
|
||||
GLint WriteFrameBuffer::clearStencilValue() const {
|
||||
bind();
|
||||
GLint ret;
|
||||
glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GLint WriteFrameBuffer::clearStencilValue(GLint s_) {
|
||||
declare();
|
||||
glClearStencil(s_);
|
||||
return s_;
|
||||
}
|
||||
|
||||
void WriteFrameBuffer::clear(GLbitfield mask_) const {
|
||||
bind();
|
||||
glClear(mask_);
|
||||
}
|
||||
|
||||
void WriteFrameBuffer::clearDepth() const {
|
||||
clear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void WriteFrameBuffer::clearDepth(float val_) const {
|
||||
bind();
|
||||
glClearBufferfv(GL_DEPTH, 0, &val_);
|
||||
}
|
||||
|
||||
void WriteFrameBuffer::clearStencil() const {
|
||||
clear(GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void WriteFrameBuffer::clearStencil(GLint val_) const {
|
||||
bind();
|
||||
glClearBufferiv(GL_STENCIL, 0, &val_);
|
||||
}
|
||||
|
||||
void WriteFrameBuffer::clearDepthStencil() const {
|
||||
clear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void WriteFrameBuffer::clearDepthStencil(float d_, GLint s_) const {
|
||||
bind();
|
||||
glClearBufferfi(GL_DEPTH_STENCIL, 0, d_, s_);
|
||||
}
|
||||
|
||||
FrameBuffer::FrameBuffer()
|
||||
: FrameBufferBase(GL_FRAMEBUFFER) {}
|
||||
|
||||
FrameBuffer& FrameBuffer::operator=(FrameBuffer&& rhs) {
|
||||
if (rhs.id()) {
|
||||
_attachments = rhs._attachments;
|
||||
_location = rhs._location;
|
||||
_locations = rhs._locations;
|
||||
rhs._attachments = {};
|
||||
rhs._locations = {};
|
||||
rhs._location = GL_NONE;
|
||||
OpenGLObject::operator=(std::move(rhs));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
FrameBuffer& FrameBuffer::operator=(ReadFrameBuffer&& rhs) {
|
||||
ReadFrameBuffer::operator=(std::move(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
FrameBuffer& FrameBuffer::operator=(WriteFrameBuffer&& rhs) {
|
||||
WriteFrameBuffer::operator=(std::move(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace nb
|
||||
@@ -0,0 +1,8 @@
|
||||
#include "Image.hpp"
|
||||
|
||||
using ImageErrorCodes = nb::ImageError::Codes;
|
||||
const std::string nb::ImageError::type = "nb::ImageError";
|
||||
const nb::ErrorCodeMap nb::ImageError::ErrorMessages = {
|
||||
{ ImageErrorCodes::UNDEFINED, "Error" },
|
||||
{ImageErrorCodes::OUT_OF_BOUNDS, "Out of bounds"}
|
||||
};
|
||||
@@ -5,7 +5,19 @@ namespace nb {
|
||||
const std::string OGLError::type = "nb::OGLError";
|
||||
const ErrorCodeMap OGLError::ErrorMessages = {
|
||||
{ OGLError::Codes::UNDEFINED, "Error" },
|
||||
{OGLError::Codes::HANGING_OBJECT, "Attempting to leave a hanging OpenGL object"}
|
||||
{OGLError::Codes::HANGING_OBJECT, "Attempting to leave a hanging OpenGL object"},
|
||||
{OGLError::Codes::INVALID_OBJECT, "Attempting operation with invalid object"}
|
||||
};
|
||||
|
||||
OpenGLObject::OpenGLObject(OpenGLObject&& rval) {
|
||||
*this = std::move(rval);
|
||||
}
|
||||
|
||||
OpenGLObject& OpenGLObject::operator=(OpenGLObject&& rhs) {
|
||||
if (_id) { THROW(OGLError(Codes::HANGING_OBJECT)); }
|
||||
_id = rhs._id;
|
||||
rhs._id = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace nb
|
||||
@@ -15,22 +15,29 @@ const ErrorCodeMap ProgramError::ErrorMessages = {
|
||||
{ProgramErrCodes::LINKING_ERROR, "Linker error"}
|
||||
};
|
||||
|
||||
Shader::Shader(GLenum target_, const std::string& source_) : target(target_) {
|
||||
Shader::Shader(GLenum target_, const std::string& source_)
|
||||
: Shader(target_, std::vector<std::string>({source_})) {}
|
||||
|
||||
Shader::Shader(GLenum target_, const std::vector<std::string>& strings_)
|
||||
: target(target_), _sources(strings_) {
|
||||
declare();
|
||||
const char* src_ptr= source_.data();
|
||||
glShaderSource(_id, 1, &src_ptr, NULL);
|
||||
glCompileShader(_id);
|
||||
_success = status(GL_COMPILE_STATUS);
|
||||
if (!_success) {
|
||||
WARN(log(), 0x0FE);
|
||||
}
|
||||
compile();
|
||||
}
|
||||
|
||||
Shader::Shader(Shader&& cpy) : target(cpy.target) {
|
||||
Shader::Shader(Shader&& cpy)
|
||||
: target(cpy.target), _success(cpy._success), _sources(cpy._sources) {
|
||||
_id = cpy._id;
|
||||
|
||||
cpy._success = false;
|
||||
cpy._sources = {};
|
||||
cpy._id = 0;
|
||||
}
|
||||
|
||||
Shader::operator bool() { return _success; }
|
||||
Shader::operator bool() { return success(); }
|
||||
|
||||
bool Shader::success() const {
|
||||
return _success;
|
||||
}
|
||||
|
||||
GLint Shader::status(GLenum parameter) const {
|
||||
GLint param = 0;
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "Textures.hpp"
|
||||
|
||||
namespace nb{
|
||||
|
||||
Texture::Texture(GLenum target_) : target(target_) {
|
||||
glGenTextures(1, &_id);
|
||||
}
|
||||
namespace nb {
|
||||
|
||||
Texture::Texture(GLenum target_) : Base(target_) {}
|
||||
|
||||
} // namespace nb
|
||||
@@ -6,8 +6,14 @@ using VAOErrorCodes = VAOError::Codes;
|
||||
const std::string VAOError::type = "nb::VAOError";
|
||||
const ErrorCodeMap VAOError::ErrorMessages = {
|
||||
{ VAOErrorCodes::UNDEFINED, "Error" },
|
||||
{ VAOErrorCodes::INVALID_ATTRIBUTE, "Targeting invalid attribute"},
|
||||
{ VAOErrorCodes::INVALID_VAO, "Targeting invalid VAO" }
|
||||
{ VAOErrorCodes::INVALID_ATTRIBUTE, "Targeting invalid attribute"}
|
||||
};
|
||||
|
||||
using VertexCodes = VertexError::Codes;
|
||||
const std::string VertexError::type = "nb::VertexError";
|
||||
const ErrorCodeMap VertexError::ErrorMessages = {
|
||||
{ VertexError::UNDEFINED, "Error" },
|
||||
{ VertexError::MISALIGNED_DATA, "Data does not match vertex layout"}
|
||||
};
|
||||
|
||||
VAO::VAO(const VertexAttributePointerList& attr_ptrs) {
|
||||
@@ -19,12 +25,9 @@ VAO::VAO(VAO&& other) {
|
||||
}
|
||||
|
||||
VAO& VAO::operator=(VAO&& rhs) {
|
||||
_id = rhs._id;
|
||||
OpenGLObject::operator=(std::move(rhs));
|
||||
_attrs = rhs._attrs;
|
||||
|
||||
rhs._id = 0;
|
||||
rhs._attrs = {};
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -115,25 +118,17 @@ VertexGroup& VertexGroup::operator=(VertexGroup&& rhs) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
VertexGroup::VertexGroup(const VertexDataVec& vertex_data_)
|
||||
: _vao(std::make_shared<VAO>()), _ebo(std::make_shared<EBO>()) {
|
||||
setBuffers(vertex_data_);
|
||||
void VertexGroup::draw() const {
|
||||
bind();
|
||||
glDrawElements(primitive, _ebo->size(), _ebo->glslType(), 0);
|
||||
}
|
||||
|
||||
VertexGroup::VertexGroup(const VertexData& vertex_data_)
|
||||
: VertexGroup(VertexDataVec({vertex_data_})) {}
|
||||
|
||||
VertexGroup::VertexGroup(
|
||||
const ByteVector& data_,
|
||||
const VertexAttributeList& attrs_
|
||||
) : VertexGroup({std::make_shared<VBO>(data_), attrs_}) {}
|
||||
|
||||
size_t VertexGroup::addBuffer(const VertexData& vertex_data_) {
|
||||
VertexData data = vertex_data_;
|
||||
_vertex_data.emplace_back(data);
|
||||
VertexAttributePointerList attrs = _vao->attributes();
|
||||
GLuint idx = attrs.size();
|
||||
for (auto attr : data.attrs) {
|
||||
for (const auto& attr : data.attrs) {
|
||||
attrs.emplace_back(
|
||||
VertexAttributePointer{attr, data.vbo->id(),idx}
|
||||
);
|
||||
@@ -143,6 +138,13 @@ size_t VertexGroup::addBuffer(const VertexData& vertex_data_) {
|
||||
return _vertex_data.size();
|
||||
}
|
||||
|
||||
size_t VertexGroup::addBuffer(const ByteVector& data_, const VertexAttributeList& attrs_) {
|
||||
return addBuffer({
|
||||
std::make_shared<VBO>(data_),
|
||||
attrs_
|
||||
});
|
||||
}
|
||||
|
||||
VertexData VertexGroup::getBuffers(size_t idx) {
|
||||
return _vertex_data[idx];
|
||||
}
|
||||
@@ -155,8 +157,8 @@ size_t VertexGroup::setBuffers(const VertexDataVec& vertex_data_) {
|
||||
_vertex_data = vertex_data_;
|
||||
VertexAttributePointerList attr_ptrs;
|
||||
GLuint idx = 0;
|
||||
for (auto data : _vertex_data) {
|
||||
for (auto attr : data.attrs) {
|
||||
for (const auto& data : _vertex_data) {
|
||||
for (const auto& attr : data.attrs) {
|
||||
attr_ptrs.emplace_back(
|
||||
VertexAttributePointer{attr, data.vbo->id(), idx}
|
||||
);
|
||||
@@ -167,9 +169,15 @@ size_t VertexGroup::setBuffers(const VertexDataVec& vertex_data_) {
|
||||
return _vertex_data.size();
|
||||
}
|
||||
|
||||
VertexDataVec VertexGroup::dropBuffers() {
|
||||
auto ret = _vertex_data;
|
||||
setBuffers({});
|
||||
return ret;
|
||||
}
|
||||
|
||||
VertexData VertexGroup::dropBuffer(size_t idx) {
|
||||
if (idx >= _vertex_data.size()) {
|
||||
THROW(BufferError(BufferError::Codes::INVALID_BUFFER));
|
||||
THROW(NBError(NBError::INDEX_ERROR));
|
||||
}
|
||||
VertexDataVec tmp;
|
||||
VertexData ret;
|
||||
@@ -228,4 +236,16 @@ void VertexGroup::enable() { _vao->enable(); }
|
||||
|
||||
void VertexGroup::disable() { _vao->disable(); }
|
||||
|
||||
std::shared_ptr<EBO> VertexGroup::indices() const { return _ebo; }
|
||||
|
||||
std::shared_ptr<EBO> VertexGroup::indices(const std::vector<uint32_t>& data) {
|
||||
_ebo->data(data);
|
||||
return _ebo;
|
||||
}
|
||||
|
||||
std::shared_ptr<EBO> VertexGroup::indices(std::shared_ptr<EBO> buffer) {
|
||||
_ebo = buffer;
|
||||
return _ebo;
|
||||
}
|
||||
|
||||
} // namespace nb
|
||||
|
||||
Reference in New Issue
Block a user