diff --git a/src/nostalgia/glutils/glutils.cpp b/src/nostalgia/glutils/glutils.cpp index b566f456..ac07616b 100644 --- a/src/nostalgia/glutils/glutils.cpp +++ b/src/nostalgia/glutils/glutils.cpp @@ -17,6 +17,14 @@ void deleteBuffer(GLuint b) noexcept { glDeleteBuffers(1, &b); } +void deleteFrameBuffer(GLuint b) noexcept { + glDeleteFramebuffers(1, &b); +} + +void deleteRenderBuffer(GLuint b) noexcept { + glDeleteRenderbuffers(1, &b); +} + void deleteTexture(GLuint t) noexcept { glDeleteTextures(1, &t); } @@ -26,6 +34,8 @@ void deleteVertexArray(GLuint v) noexcept { } template struct GLObject; +template struct GLObject; +template struct GLObject; template struct GLObject; template struct GLObject; template struct GLObject; @@ -44,10 +54,9 @@ static ox::Result buildShader(GLuint shaderType, const GLchar *src, co oxErrorf("shader compile error in {}: {}", shaderName, errMsg); return OxError(1, "shader compile error"); } - return ox::move(shader); + return shader; } -[[nodiscard]] ox::Result buildShaderProgram(const GLchar *vert, const GLchar *frag) noexcept { oxRequire(vs, buildShader(GL_VERTEX_SHADER, vert, "vshad")); oxRequire(fs, buildShader(GL_FRAGMENT_SHADER, frag, "fshad")); @@ -55,7 +64,30 @@ ox::Result buildShaderProgram(const GLchar *vert, const GLchar *frag) glAttachShader(prgm, vs); glAttachShader(prgm, fs); glLinkProgram(prgm); - return ox::move(prgm); + return prgm; +} + +FrameBuffer generateFrameBuffer(int width, int height) noexcept { + FrameBuffer fb; + glGenFramebuffers(1, &fb.fbo.id); + glBindFramebuffer(GL_FRAMEBUFFER, fb); + // color texture + glGenTextures(1, &fb.color.id); + glBindTexture(GL_TEXTURE_2D, fb.color); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb.color, 0); + // depth texture + glGenRenderbuffers(1, &fb.depth.id); + glBindRenderbuffer(GL_RENDERBUFFER, fb.depth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb.depth, 0); + // verify FBO + oxAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame Buffer is incomplete"); + // restore primary FB + glBindFramebuffer(GL_FRAMEBUFFER, 0); + return fb; } } diff --git a/src/nostalgia/glutils/glutils.hpp b/src/nostalgia/glutils/glutils.hpp index 34f74bb1..f1006899 100644 --- a/src/nostalgia/glutils/glutils.hpp +++ b/src/nostalgia/glutils/glutils.hpp @@ -6,11 +6,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#pragma once + #include #define GL_GLEXT_PROTOTYPES 1 #ifdef OX_OS_Darwin +#ifndef GL_SILENCE_DEPRECATION #define GL_SILENCE_DEPRECATION +#endif #include #else #include @@ -63,7 +67,7 @@ struct GLObject: public Base { o.id = 0; } - ~GLObject() { + ~GLObject() noexcept { del(id); } @@ -94,22 +98,51 @@ struct GLObject: public Base { }; void deleteBuffer(GLuint b) noexcept; +void deleteFrameBuffer(GLuint b) noexcept; +void deleteRenderBuffer(GLuint b) noexcept; void deleteTexture(GLuint t) noexcept; void deleteVertexArray(GLuint v) noexcept; extern template struct GLObject; +extern template struct GLObject; +extern template struct GLObject; extern template struct GLObject; extern template struct GLObject; extern template struct GLObject; extern template struct GLObject; using GLBuffer = GLObject; +using GLFrameBuffer = GLObject; +using GLRenderBuffer = GLObject; using GLShader = GLObject; using GLProgram = GLObject; using GLTexture = GLObject; using GLVertexArray = GLObject; +/** + * FrameBuffer holds everything needed for a usable frame buffer to exist. + * It differs from GLFrameBuffer in that GLFrameBuffer only manages the FBO + * and not its dependencies. + */ +struct FrameBuffer { + GLFrameBuffer fbo; + GLTexture color; + GLRenderBuffer depth; + + constexpr operator GLuint&() noexcept { + return fbo.id; + } + + constexpr operator const GLuint&() const noexcept { + return fbo.id; + } +}; + + [[nodiscard]] ox::Result buildShaderProgram(const GLchar *vert, const GLchar *frag) noexcept; -} +[[nodiscard]] +FrameBuffer generateFrameBuffer(int width, int height) noexcept; + +} \ No newline at end of file