3
// Copyright (C) 2010-2020, the Celestia Development Team
4
// Original version by Chris Laurel <claurel@gmail.com>
6
// This program is free software; you can redistribute it and/or
7
// modify it under the terms of the GNU General Public License
8
// as published by the Free Software Foundation; either version 2
9
// of the License, or (at your option) any later version.
11
#include "framebuffer.h"
13
FramebufferObject::FramebufferObject(GLuint width, GLuint height, unsigned int attachments) :
19
m_status(GL_FRAMEBUFFER_UNSUPPORTED)
23
generateFbo(attachments);
27
FramebufferObject::FramebufferObject(FramebufferObject &&other) noexcept:
28
m_width(other.m_width),
29
m_height(other.m_height),
30
m_colorTexId(other.m_colorTexId),
31
m_depthTexId(other.m_depthTexId),
32
m_fboId(other.m_fboId),
33
m_status(other.m_status)
36
other.m_status = GL_FRAMEBUFFER_UNSUPPORTED;
39
FramebufferObject& FramebufferObject::operator=(FramebufferObject &&other) noexcept
41
m_width = other.m_width;
42
m_height = other.m_height;
43
m_colorTexId = other.m_colorTexId;
44
m_depthTexId = other.m_depthTexId;
45
m_fboId = other.m_fboId;
46
m_status = other.m_status;
49
other.m_status = GL_FRAMEBUFFER_UNSUPPORTED;
53
FramebufferObject::~FramebufferObject()
59
FramebufferObject::isValid() const
61
return m_status == GL_FRAMEBUFFER_COMPLETE;
65
FramebufferObject::colorTexture() const
71
FramebufferObject::depthTexture() const
77
FramebufferObject::generateColorTexture()
79
// Create and bind the texture
80
glGenTextures(1, &m_colorTexId);
81
glBindTexture(GL_TEXTURE_2D, m_colorTexId);
83
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
84
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
87
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
88
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
90
// Set the texture dimensions
91
// Do we need to set GL_DEPTH_COMPONENT24 here?
93
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
95
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
99
glBindTexture(GL_TEXTURE_2D, 0);
103
#define CEL_DEPTH_FORMAT GL_UNSIGNED_INT
105
#define CEL_DEPTH_FORMAT GL_UNSIGNED_BYTE
109
FramebufferObject::generateDepthTexture()
111
// Create and bind the texture
112
glGenTextures(1, &m_depthTexId);
113
glBindTexture(GL_TEXTURE_2D, m_depthTexId);
116
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
117
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
120
// Only nearest sampling is appropriate for depth textures
121
// But we can use linear to decrease aliasing
122
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
123
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
126
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
127
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
129
// Set the texture dimensions
130
// Do we need to set GL_DEPTH_COMPONENT24 here?
132
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, m_width, m_height, 0, GL_DEPTH_COMPONENT, CEL_DEPTH_FORMAT, nullptr);
134
// Unbind the texture
135
glBindTexture(GL_TEXTURE_2D, 0);
139
FramebufferObject::generateFbo(unsigned int attachments)
142
glGenFramebuffers(1, &m_fboId);
144
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFboId);
145
glBindFramebuffer(GL_FRAMEBUFFER, m_fboId);
148
glReadBuffer(GL_NONE);
151
if ((attachments & ColorAttachment) != 0)
153
generateColorTexture();
154
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorTexId, 0);
155
m_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
156
if (m_status != GL_FRAMEBUFFER_COMPLETE)
158
glBindFramebuffer(GL_FRAMEBUFFER, oldFboId);
166
// Depth-only rendering; no color buffer.
167
glDrawBuffer(GL_NONE);
171
if ((attachments & DepthAttachment) != 0)
173
generateDepthTexture();
174
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTexId, 0);
175
m_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
176
if (m_status != GL_FRAMEBUFFER_COMPLETE)
178
glBindFramebuffer(GL_FRAMEBUFFER, oldFboId);
185
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
188
// Restore default frame buffer
189
glBindFramebuffer(GL_FRAMEBUFFER, oldFboId);
192
// Delete all GL objects associated with this framebuffer object
194
FramebufferObject::cleanup()
198
glDeleteFramebuffers(1, &m_fboId);
201
if (m_colorTexId != 0)
203
glDeleteTextures(1, &m_colorTexId);
206
if (m_depthTexId != 0)
208
glDeleteTextures(1, &m_depthTexId);
213
FramebufferObject::bind()
217
glBindFramebuffer(GL_FRAMEBUFFER, m_fboId);
225
FramebufferObject::unbind(GLint oldfboId)
227
glBindFramebuffer(GL_FRAMEBUFFER, oldfboId);