Huge graphics overhaul
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
#pragma once
|
||||
#ifndef _NB_FRAMEBUFFER
|
||||
#define _NB_FRAMEBUFFER
|
||||
|
||||
#include "GLLoad.hpp"
|
||||
|
||||
#include <NBCore/Errors.hpp>
|
||||
|
||||
#include "Image.hpp"
|
||||
#include "OGLObjects.hpp"
|
||||
#include "Textures.hpp"
|
||||
|
||||
namespace nb {
|
||||
|
||||
class FrameBufferError : public Error<FrameBufferError> {
|
||||
protected:
|
||||
using Base = Error<FrameBufferError>;
|
||||
|
||||
public:
|
||||
using Base::Base;
|
||||
enum Codes : unsigned int {
|
||||
UNDEFINED, INVALID_VALUE
|
||||
};
|
||||
static const std::string type;
|
||||
static const ErrorCodeMap ErrorMessages;
|
||||
};
|
||||
|
||||
class RenderBuffer : public RenderTarget {
|
||||
protected:
|
||||
GLuint declare() override {
|
||||
if (!_id) {
|
||||
glRenderbufferStorage(
|
||||
GL_RENDERBUFFER,
|
||||
format,
|
||||
width,
|
||||
height
|
||||
);
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
void remove() override {
|
||||
if (_id) {
|
||||
unbind();
|
||||
glDeleteRenderbuffers(1, &_id);
|
||||
_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
const unsigned int width;
|
||||
const unsigned int height;
|
||||
const GLenum format;
|
||||
template<typename PixelType>
|
||||
RenderBuffer(unsigned int width_, unsigned int height_) :
|
||||
width(width_),
|
||||
height(height_),
|
||||
format(OGLPixelFormat<PixelType>::glFormat),
|
||||
RenderTarget(GL_RENDERBUFFER)
|
||||
{ declare(); }
|
||||
RenderBuffer(RenderBuffer&& rhs) :
|
||||
width(rhs.width),
|
||||
height(rhs.height),
|
||||
format(rhs.format),
|
||||
RenderTarget(std::move(rhs))
|
||||
{}
|
||||
RenderBuffer& operator=(RenderBuffer&&) = delete;
|
||||
void bind() const override {
|
||||
if (_id) {
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _id);
|
||||
} else {
|
||||
THROW(OGLError(
|
||||
OGLError::Codes::INVALID_OBJECT,
|
||||
"w/ RenderBuffer"
|
||||
));
|
||||
}
|
||||
}
|
||||
void unbind() const override {
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class FrameBufferBase : public OpenGLObject {
|
||||
private:
|
||||
static bool texTypeIs2D(GLenum texType) {
|
||||
switch(texType) {
|
||||
case GL_TEXTURE_2D:
|
||||
default:
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
using AttachmentMap = std::unordered_map<GLenum, std::shared_ptr<RenderTarget>>;
|
||||
AttachmentMap _attachments;
|
||||
FrameBufferBase(GLenum target);
|
||||
GLuint declare() override;
|
||||
void remove() override;
|
||||
std::shared_ptr<RenderTarget> detach(GLenum);
|
||||
void attach(
|
||||
GLenum attachment,
|
||||
std::shared_ptr<Texture> texture,
|
||||
unsigned int level=0
|
||||
);
|
||||
void attach(
|
||||
GLenum attachment,
|
||||
std::shared_ptr<Texture> texture,
|
||||
unsigned int level,
|
||||
unsigned int layer
|
||||
);
|
||||
void attach(
|
||||
GLenum attachment,
|
||||
std::shared_ptr<RenderBuffer> renderBuffer
|
||||
) {
|
||||
declare();
|
||||
if (attachment == GL_NONE) {
|
||||
THROW(FrameBufferError(FrameBufferError::INVALID_VALUE,
|
||||
"Cannot attach RenderBuffer to `GL_NONE`"
|
||||
));
|
||||
}
|
||||
glFramebufferRenderbuffer(
|
||||
Target,
|
||||
attachment,
|
||||
GL_RENDERBUFFER,
|
||||
renderBuffer->id()
|
||||
);
|
||||
_attachments[attachment] = renderBuffer;
|
||||
}
|
||||
|
||||
public:
|
||||
const GLenum Target;
|
||||
void bind() const override;
|
||||
void unbind() const override;
|
||||
GLenum status() const;
|
||||
AttachmentMap getAllBuffers() const;
|
||||
std::shared_ptr<RenderTarget> getBuffer(GLenum) const;
|
||||
};
|
||||
|
||||
class ReadFrameBuffer;
|
||||
class WriteFrameBuffer;
|
||||
|
||||
class ReadFrameBuffer : public virtual FrameBufferBase {
|
||||
friend WriteFrameBuffer;
|
||||
protected:
|
||||
using FrameBufferBase::_attachments;
|
||||
GLenum _location;
|
||||
|
||||
public:
|
||||
using FrameBufferBase::attach;
|
||||
ReadFrameBuffer();
|
||||
ReadFrameBuffer& operator=(WriteFrameBuffer&&);
|
||||
ReadFrameBuffer& operator=(ReadFrameBuffer&&);
|
||||
std::shared_ptr<RenderTarget> getReadBuffer() const;
|
||||
GLenum getReadLocation() const;
|
||||
std::shared_ptr<RenderTarget> setReadBuffer(GLenum attachment);
|
||||
template<typename T, typename... Args>
|
||||
std::shared_ptr<RenderTarget> setReadBuffer(
|
||||
GLenum attachment,
|
||||
std::shared_ptr<T> target,
|
||||
Args... args
|
||||
) {
|
||||
declare();
|
||||
FrameBufferBase::attach(attachment, target, args...);
|
||||
setReadBuffer(attachment);
|
||||
return getReadBuffer();
|
||||
}
|
||||
};
|
||||
|
||||
class WriteFrameBuffer : public virtual FrameBufferBase {
|
||||
friend ReadFrameBuffer;
|
||||
protected:
|
||||
using DrawTexVec = std::vector<std::shared_ptr<Texture>>;
|
||||
using FrameBufferBase::_attachments;
|
||||
std::vector<GLenum> _locations;
|
||||
|
||||
public:
|
||||
WriteFrameBuffer();
|
||||
WriteFrameBuffer& operator=(ReadFrameBuffer&&);
|
||||
WriteFrameBuffer& operator=(WriteFrameBuffer&&);
|
||||
template<typename... T>
|
||||
void attach(
|
||||
GLenum attachment,
|
||||
std::shared_ptr<Texture> texture,
|
||||
T... args
|
||||
) { FrameBufferBase::attach(attachment, texture, args...); }
|
||||
DrawTexVec getWriteBuffers() const;
|
||||
std::vector<GLenum> getWriteLocations() const;
|
||||
DrawTexVec setWriteBuffers(const std::vector<GLenum>& attachments);
|
||||
std::shared_ptr<Texture> setWriteBuffer(GLenum attachment);
|
||||
template<typename... T>
|
||||
std::shared_ptr<Texture> setWriteBuffer(
|
||||
GLenum attachment,
|
||||
std::shared_ptr<Texture> texture,
|
||||
T... args
|
||||
) {
|
||||
attach(attachment, texture, args...);
|
||||
setWriteBuffer(attachment);
|
||||
return std::static_pointer_cast<Texture>(_attachments.at(attachment));
|
||||
}
|
||||
|
||||
RGBA<float> clearColorValue() const;
|
||||
RGBA<float> clearColorValue(const RGBA<float>&);
|
||||
RGBA<float> clearColorValue(float r, float g, float b, float a);
|
||||
double clearDepthValue() const;
|
||||
double clearDepthValue(double);
|
||||
GLint clearStencilValue() const;
|
||||
GLint clearStencilValue(GLint);
|
||||
void clear(GLbitfield mask=(
|
||||
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT
|
||||
)) const;
|
||||
void clearColor() const;
|
||||
void clearDepth() const;
|
||||
void clearDepth(float) const;
|
||||
void clearStencil() const;
|
||||
void clearStencil(GLint) const;
|
||||
void clearDepthStencil() const;
|
||||
void clearDepthStencil(float, GLint) const;
|
||||
};
|
||||
|
||||
class FrameBuffer : public ReadFrameBuffer, public WriteFrameBuffer {
|
||||
protected:
|
||||
using FrameBufferBase::_attachments;
|
||||
using ReadFrameBuffer::_location;
|
||||
using WriteFrameBuffer::_locations;
|
||||
|
||||
public:
|
||||
FrameBuffer();
|
||||
FrameBuffer& operator=(FrameBuffer&&);
|
||||
FrameBuffer& operator=(ReadFrameBuffer&&);
|
||||
FrameBuffer& operator=(WriteFrameBuffer&&);
|
||||
};
|
||||
|
||||
} // namespace nb
|
||||
|
||||
#endif // _NB_FRAMEBUFFER
|
||||
Reference in New Issue
Block a user