#include "XCEngine/RHI/OpenGL/OpenGLRenderTargetView.h" #include "XCEngine/RHI/OpenGL/OpenGLEnums.h" #include namespace XCEngine { namespace RHI { OpenGLRenderTargetView::OpenGLRenderTargetView() : m_texture(0) , m_framebuffer(0) , m_mipLevel(0) , m_width(0) , m_height(0) , m_type(RenderTargetType::Texture2D) { } OpenGLRenderTargetView::~OpenGLRenderTargetView() { Shutdown(); } bool OpenGLRenderTargetView::Initialize(unsigned int texture, const OpenGLRenderTargetViewDesc& desc) { m_texture = texture; m_mipLevel = desc.mipLevel; m_type = desc.type; glGenFramebuffers(1, &m_framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); unsigned int target = ToOpenGL(desc.type); GLenum attachment = GL_COLOR_ATTACHMENT0; switch (desc.type) { case RenderTargetType::Texture2D: glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture, desc.mipLevel); break; case RenderTargetType::Texture2DArray: glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment, texture, desc.mipLevel, desc.baseArraySlice); break; case RenderTargetType::Texture3D: glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment, texture, desc.mipLevel, desc.layer); break; case RenderTargetType::TextureCube: glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X + desc.baseArraySlice, texture, desc.mipLevel); break; case RenderTargetType::TextureCubeArray: glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment, texture, desc.mipLevel, desc.baseArraySlice); break; } if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { glBindFramebuffer(GL_FRAMEBUFFER, 0); return false; } glBindFramebuffer(GL_FRAMEBUFFER, 0); return true; } bool OpenGLRenderTargetView::Initialize(unsigned int texture, int mipLevel) { OpenGLRenderTargetViewDesc desc; desc.type = RenderTargetType::Texture2D; desc.mipLevel = mipLevel; return Initialize(texture, desc); } bool OpenGLRenderTargetView::InitializeCubemap(unsigned int cubemap, int face, int mipLevel) { m_texture = cubemap; m_mipLevel = mipLevel; m_type = RenderTargetType::TextureCube; glGenFramebuffers(1, &m_framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, cubemap, mipLevel); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { glBindFramebuffer(GL_FRAMEBUFFER, 0); return false; } glBindFramebuffer(GL_FRAMEBUFFER, 0); return true; } void OpenGLRenderTargetView::Shutdown() { if (m_framebuffer) { glDeleteFramebuffers(1, &m_framebuffer); m_framebuffer = 0; } if (!m_framebuffers.empty()) { glDeleteFramebuffers(static_cast(m_framebuffers.size()), m_framebuffers.data()); m_framebuffers.clear(); } } void OpenGLRenderTargetView::Bind(unsigned int slot) { glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); (void)slot; } void OpenGLRenderTargetView::Bind(unsigned int count, const unsigned int* framebuffers, const int* drawBuffers) { if (count == 1) { glBindFramebuffer(GL_FRAMEBUFFER, framebuffers[0]); } else { glBindFramebuffer(GL_FRAMEBUFFER, 0); for (unsigned int i = 0; i < count; i++) { glBindFramebuffer(GL_FRAMEBUFFER, framebuffers[i]); glDrawBuffers(1, (const GLenum*)&drawBuffers[i]); } } (void)count; } void OpenGLRenderTargetView::Unbind() { glBindFramebuffer(GL_FRAMEBUFFER, 0); } void OpenGLRenderTargetView::Clear(float r, float g, float b, float a) { glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); glClearColor(r, g, b, a); glClear(GL_COLOR_BUFFER_BIT); } void OpenGLRenderTargetView::Clear(float r, float g, float b, float a, float depth, uint8_t stencil) { glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); glClearColor(r, g, b, a); glClearDepth(depth); glClearStencil(stencil); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } void OpenGLRenderTargetView::BindFramebuffer(unsigned int framebuffer) { glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); } void OpenGLRenderTargetView::UnbindFramebuffer() { glBindFramebuffer(GL_FRAMEBUFFER, 0); } } // namespace RHI } // namespace XCEngine