Renderer: Implement Framebuffers

This commit is contained in:
Jérôme Leclercq
2021-02-20 19:22:08 +01:00
parent 3ef74d6e1d
commit fb3468854f
32 changed files with 401 additions and 100 deletions

View File

@@ -0,0 +1,92 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - OpenGL Renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderPass.hpp>
#include <Nazara/OpenGLRenderer/OpenGLTexture.hpp>
#include <stdexcept>
#include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz
{
OpenGLFboFramebuffer::OpenGLFboFramebuffer(OpenGLDevice& device, const std::vector<std::shared_ptr<Texture>>& attachments) :
OpenGLFramebuffer(OpenGLFramebuffer::Type::FBO)
{
if (!m_framebuffer.Create(device))
throw std::runtime_error("failed to create framebuffer object");
std::size_t colorAttachmentCount = 0;
bool hasDepth = false;
bool hasStencil = false;
for (std::size_t i = 0; i < attachments.size(); ++i)
{
assert(attachments[i]);
const OpenGLTexture& glTexture = static_cast<const OpenGLTexture&>(*attachments[i]);
PixelFormat textureFormat = glTexture.GetFormat();
GLenum attachment;
switch (PixelFormatInfo::GetContent(textureFormat))
{
case PixelFormatContent_ColorRGBA:
attachment = GL_COLOR_ATTACHMENT0 + colorAttachmentCount;
colorAttachmentCount++;
break;
case PixelFormatContent_Depth:
if (hasDepth)
throw std::runtime_error("a framebuffer can only have one depth attachment");
attachment = GL_DEPTH_ATTACHMENT;
hasDepth = true;
break;
case PixelFormatContent_DepthStencil:
if (hasDepth)
throw std::runtime_error("a framebuffer can only have one depth attachment");
if (hasStencil)
throw std::runtime_error("a framebuffer can only have one stencil attachment");
attachment = GL_DEPTH_STENCIL_ATTACHMENT;
hasDepth = true;
hasStencil = true;
break;
case PixelFormatContent_Stencil:
if (hasStencil)
throw std::runtime_error("a framebuffer can only have one stencil attachment");
attachment = GL_STENCIL_ATTACHMENT;
hasStencil = true;
break;
case PixelFormatContent_Undefined:
default:
throw std::runtime_error("unhandled pixel format " + PixelFormatInfo::GetName(textureFormat));
}
m_framebuffer.Texture2D(attachment, ToOpenGL(OpenGLTexture::ToTextureTarget(glTexture.GetType())), glTexture.GetTexture().GetObjectId());
}
GLenum status = m_framebuffer.Check();
if (status != GL_FRAMEBUFFER_COMPLETE)
throw std::runtime_error("invalid framebuffer: 0x" + NumberToString(status, 16));
m_colorAttachmentCount = colorAttachmentCount;
}
void OpenGLFboFramebuffer::Activate() const
{
const GL::Context& context = m_framebuffer.EnsureDeviceContext();
context.BindFramebuffer(GL::FramebufferTarget::Draw, m_framebuffer.GetObjectId());
}
std::size_t OpenGLFboFramebuffer::GetColorBufferCount() const
{
return m_colorAttachmentCount;
}
}