236 lines
6.4 KiB
C++
236 lines
6.4 KiB
C++
#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
|