feat: Add OpenGL renderbuffer abstraction

This commit is contained in:
Vsevolod Kremianskii 2021-02-14 11:59:34 +07:00
parent df61386f9a
commit 88c78c8bae
10 changed files with 187 additions and 50 deletions

View file

@ -169,6 +169,7 @@ set(RENDER_HEADERS
src/render/model/modelnode.h
src/render/model/models.h
src/render/pbribl.h
src/render/renderbuffer.h
src/render/shaders.h
src/render/stateutil.h
src/render/texture.h
@ -205,6 +206,7 @@ set(RENDER_SOURCES
src/render/model/modelnode.cpp
src/render/model/models.cpp
src/render/pbribl.cpp
src/render/renderbuffer.cpp
src/render/shaders.cpp
src/render/stateutil.cpp
src/render/texture.cpp

View file

@ -76,6 +76,10 @@ void Framebuffer::attachDepth(const Texture &texture) const {
}
}
void Framebuffer::attachDepth(const Renderbuffer &renderbuffer) const {
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer.id());
}
void Framebuffer::checkCompleteness() {
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
throw logic_error("Framebuffer is not complete");

View file

@ -17,6 +17,11 @@
#pragma once
#include <cstdint>
#include <boost/noncopyable.hpp>
#include "renderbuffer.h"
#include "texture.h"
namespace reone {
@ -26,7 +31,7 @@ namespace render {
/**
* Abstraction over the OpenGL framebuffer used for off-screen rendering.
*/
class Framebuffer {
class Framebuffer : boost::noncopyable {
public:
Framebuffer() = default;
~Framebuffer();
@ -53,6 +58,8 @@ public:
*/
void attachDepth(const Texture &texture) const;
void attachDepth(const Renderbuffer &renderbuffer) const;
/**
* Throws logic_error if this framebuffer is not complete. Framebuffer must be bound.
*/
@ -61,9 +68,6 @@ public:
private:
bool _inited { false };
uint32_t _framebuffer { 0 };
Framebuffer(const Framebuffer &) = delete;
Framebuffer &operator=(const Framebuffer &) = delete;
};
} // namespace render

View file

@ -17,15 +17,16 @@
#include "pbribl.h"
#include "glm/ext.hpp"
#include "GL/glew.h"
#include "SDL2/SDL_opengl.h"
#include "glm/ext.hpp"
#include "meshes.h"
#include "renderbuffer.h"
#include "shaders.h"
#include "stateutil.h"
#include "texture.h"
#include "textureutil.h"
using namespace std;
@ -103,10 +104,10 @@ shared_ptr<Texture> PBRIBL::computeIrradianceMap(const Texture *envmap) {
irradianceColor->bind();
irradianceColor->clearPixels(32, 32, Texture::PixelFormat::RGB);
auto irradianceDepth = make_shared<Texture>(envmap->name() + "_irradiance_depth", getTextureProperties(TextureUsage::DepthBuffer));
auto irradianceDepth = make_shared<Renderbuffer>();
irradianceDepth->init();
irradianceDepth->bind();
irradianceDepth->clearPixels(32, 32, Texture::PixelFormat::Depth);
irradianceDepth->configure(32, 32, Renderbuffer::PixelFormat::Depth);
_irradianceFB.bind();
@ -142,10 +143,10 @@ shared_ptr<Texture> PBRIBL::computePrefilterMap(const Texture *envmap) {
prefilterColor->bind();
prefilterColor->clearPixels(128, 128, Texture::PixelFormat::RGB);
auto prefilterDepth = make_shared<Texture>(envmap->name() + "_prefilter_depth", getTextureProperties(TextureUsage::DepthBuffer));
auto prefilterDepth = make_shared<Renderbuffer>();
prefilterDepth->init();
prefilterDepth->bind();
prefilterDepth->clearPixels(128, 128, Texture::PixelFormat::Depth);
prefilterDepth->configure(128, 128, Renderbuffer::PixelFormat::Depth);
_prefilterFB.bind();
@ -192,10 +193,10 @@ shared_ptr<Texture> PBRIBL::computeBRDFLookup(const Texture *envmap) {
brdfLookupColor->bind();
brdfLookupColor->clearPixels(512, 512, Texture::PixelFormat::RGB);
auto brdfLookupDepth = make_shared<Texture>(envmap->name() + "_brdf_depth", getTextureProperties(TextureUsage::DepthBuffer));
auto brdfLookupDepth = make_shared<Renderbuffer>();
brdfLookupDepth->init();
brdfLookupDepth->bind();
brdfLookupDepth->clearPixels(512, 512, Texture::PixelFormat::Depth);
brdfLookupDepth->configure(512, 512, Renderbuffer::PixelFormat::Depth);
_brdfLookupFB.bind();
_brdfLookupFB.attachColor(*brdfLookupColor);

View file

@ -0,0 +1,73 @@
/*
* Copyright (c) 2020-2021 The reone project contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "renderbuffer.h"
#include "GL/glew.h"
#include "SDL2/SDL_opengl.h"
namespace reone {
namespace render {
void Renderbuffer::init() {
if (!_inited) {
glGenRenderbuffers(1, &_id);
_inited = true;
}
}
Renderbuffer::~Renderbuffer() {
deinit();
}
void Renderbuffer::deinit() {
if (_inited) {
glDeleteRenderbuffers(1, &_id);
_inited = false;
}
}
void Renderbuffer::bind() const {
if (_inited) {
glBindRenderbuffer(GL_RENDERBUFFER, _id);
}
}
void Renderbuffer::unbind() const {
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}
static GLenum getInternalFormatGL(Renderbuffer::PixelFormat format) {
switch (format) {
case Renderbuffer::PixelFormat::Depth:
return GL_DEPTH_COMPONENT;
case Renderbuffer::PixelFormat::RGB:
return GL_RGB8;
case Renderbuffer::PixelFormat::RGBA:
default:
return GL_RGBA8;
}
}
void Renderbuffer::configure(int w, int h, PixelFormat format) {
glRenderbufferStorage(GL_RENDERBUFFER, getInternalFormatGL(format), w, h);
}
} // namespace render
} // namespace reone

62
src/render/renderbuffer.h Normal file
View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2020-2021 The reone project contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <cstdint>
#include <boost/noncopyable.hpp>
namespace reone {
namespace render {
/**
* Abstraction over the OpenGL renderbuffer.
*/
class Renderbuffer : boost::noncopyable {
public:
enum class PixelFormat {
Depth,
RGB,
RGBA
};
Renderbuffer() = default;
~Renderbuffer();
void init();
void deinit();
void bind() const;
void unbind() const;
/**
* Configures this renderbuffers size and internal format. Renderbuffer must be bound.
*/
void configure(int w, int h, PixelFormat format);
uint32_t id() const { return _id; }
private:
bool _inited { false };
uint32_t _id { 0 };
};
} // namespace render
} // namespace reone

View file

@ -17,10 +17,10 @@
#include "control.h"
#include "glm/ext.hpp"
#include "GL/glew.h"
#include "glm/ext.hpp"
#include "../../render/meshes.h"
#include "../../render/shaders.h"
#include "../../render/stateutil.h"
@ -45,10 +45,10 @@ void ControlRenderPipeline::init() {
_geometryColor->clearPixels(_extent[2], _extent[3], Texture::PixelFormat::RGBA);
_geometryColor->unbind();
_geometryDepth = make_unique<Texture>("geometry_depth", getTextureProperties(TextureUsage::DepthBuffer));
_geometryDepth = make_unique<Renderbuffer>();
_geometryDepth->init();
_geometryDepth->bind();
_geometryDepth->clearPixels(_extent[2], _extent[3], Texture::PixelFormat::Depth);
_geometryDepth->configure(_extent[2], _extent[3], Renderbuffer::PixelFormat::Depth);
_geometryDepth->unbind();
_geometry.init();

View file

@ -17,10 +17,14 @@
#pragma once
#include <boost/noncopyable.hpp>
#include "glm/vec2.hpp"
#include "glm/vec4.hpp"
#include "../../render/framebuffer.h"
#include "../../render/renderbuffer.h"
#include "../../render/texture.h"
#include "../scenegraph.h"
@ -28,7 +32,7 @@ namespace reone {
namespace scene {
class ControlRenderPipeline {
class ControlRenderPipeline : boost::noncopyable {
public:
ControlRenderPipeline(SceneGraph *scene, const glm::ivec4 &extent);
@ -41,10 +45,7 @@ private:
render::Framebuffer _geometry;
std::unique_ptr<render::Texture> _geometryColor;
std::unique_ptr<render::Texture> _geometryDepth;
ControlRenderPipeline(const ControlRenderPipeline &) = delete;
ControlRenderPipeline &operator=(const ControlRenderPipeline &) = delete;
std::unique_ptr<render::Renderbuffer> _geometryDepth;
};
} // namespace scene

View file

@ -49,6 +49,15 @@ WorldRenderPipeline::WorldRenderPipeline(SceneGraph *scene, const GraphicsOption
}
void WorldRenderPipeline::init() {
// Reusable depth renderbuffer
_depthRenderbuffer = make_unique<Renderbuffer>();
_depthRenderbuffer->init();
_depthRenderbuffer->bind();
_depthRenderbuffer->configure(_opts.width, _opts.height, Renderbuffer::PixelFormat::Depth);
_depthRenderbuffer->unbind();
// Geometry framebuffer
_geometryColor1 = make_unique<Texture>("geometry_color1", getTextureProperties(TextureUsage::ColorBuffer));
@ -63,17 +72,11 @@ void WorldRenderPipeline::init() {
_geometryColor2->clearPixels(_opts.width, _opts.height, Texture::PixelFormat::RGB);
_geometryColor2->unbind();
_geometryDepth = make_unique<Texture>("geometry_depth", getTextureProperties(TextureUsage::DepthBuffer));
_geometryDepth->init();
_geometryDepth->bind();
_geometryDepth->clearPixels(_opts.width, _opts.height, Texture::PixelFormat::Depth);
_geometryDepth->unbind();
_geometry.init();
_geometry.bind();
_geometry.attachColor(*_geometryColor1, 0);
_geometry.attachColor(*_geometryColor2, 1);
_geometry.attachDepth(*_geometryDepth);
_geometry.attachDepth(*_depthRenderbuffer);
_geometry.checkCompleteness();
_geometry.unbind();
@ -86,16 +89,10 @@ void WorldRenderPipeline::init() {
_verticalBlurColor->clearPixels(_opts.width, _opts.height, Texture::PixelFormat::RGB);
_verticalBlurColor->unbind();
_verticalBlurDepth = make_unique<Texture>("verticalblur_depth", getTextureProperties(TextureUsage::DepthBuffer));
_verticalBlurDepth->init();
_verticalBlurDepth->bind();
_verticalBlurDepth->clearPixels(_opts.width, _opts.height, Texture::PixelFormat::Depth);
_verticalBlurDepth->unbind();
_verticalBlur.init();
_verticalBlur.bind();
_verticalBlur.attachColor(*_verticalBlurColor);
_verticalBlur.attachDepth(*_verticalBlurDepth);
_verticalBlur.attachDepth(*_depthRenderbuffer);
_verticalBlur.checkCompleteness();
_verticalBlur.unbind();
@ -108,16 +105,10 @@ void WorldRenderPipeline::init() {
_horizontalBlurColor->clearPixels(_opts.width, _opts.height, Texture::PixelFormat::RGB);
_horizontalBlurColor->unbind();
_horizontalBlurDepth = make_unique<Texture>("horizontalblur_depth", getTextureProperties(TextureUsage::DepthBuffer));
_horizontalBlurDepth->init();
_horizontalBlurDepth->bind();
_horizontalBlurDepth->clearPixels(_opts.width, _opts.height, Texture::PixelFormat::Depth);
_horizontalBlurDepth->unbind();
_horizontalBlur.init();
_horizontalBlur.bind();
_horizontalBlur.attachColor(*_horizontalBlurColor);
_horizontalBlur.attachDepth(*_horizontalBlurDepth);
_horizontalBlur.attachDepth(*_depthRenderbuffer);
_horizontalBlur.checkCompleteness();
_horizontalBlur.unbind();

View file

@ -17,9 +17,13 @@
#pragma once
#include <boost/noncopyable.hpp>
#include "glm/mat4x4.hpp"
#include "../../render/framebuffer.h"
#include "../../render/renderbuffer.h"
#include "../../render/texture.h"
#include "../../render/types.h"
#include "../../scene/scenegraph.h"
@ -27,7 +31,7 @@ namespace reone {
namespace scene {
class WorldRenderPipeline {
class WorldRenderPipeline : boost::noncopyable {
public:
WorldRenderPipeline(SceneGraph *scene, const render::GraphicsOptions &opts);
@ -49,20 +53,15 @@ private:
// Framebuffer targets
std::unique_ptr<render::Renderbuffer> _depthRenderbuffer;
std::unique_ptr<render::Texture> _geometryColor1;
std::unique_ptr<render::Texture> _geometryColor2;
std::unique_ptr<render::Texture> _geometryDepth;
std::unique_ptr<render::Texture> _verticalBlurColor;
std::unique_ptr<render::Texture> _verticalBlurDepth;
std::unique_ptr<render::Texture> _horizontalBlurColor;
std::unique_ptr<render::Texture> _horizontalBlurDepth;
std::unique_ptr<render::Texture> _shadowsDepth;
// END Framebuffers targets
WorldRenderPipeline(const WorldRenderPipeline &) = delete;
WorldRenderPipeline &operator=(const WorldRenderPipeline &) = delete;
void drawShadows() const;
void drawGeometry() const;
void applyHorizontalBlur() const;