This repository has been archived on 2022-05-21. You can view files and clone it, but cannot push or open issues or pull requests.
LEFTONE/util/gleasy/framebuffer.c

97 lines
2.7 KiB
C
Raw Normal View History

#include "./framebuffer.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include "./texture.h"
void gleasy_framebuffer_initialize(
gleasy_framebuffer_t* fb, int32_t width, int32_t height, int32_t samples) {
assert(fb != NULL);
assert(width > 0);
assert(height > 0);
assert(0 < samples && samples < GL_MAX_SAMPLES);
*fb = (typeof(*fb)) {
.width = width,
.height = height,
};
glGenRenderbuffers(1, &fb->colorbuf_msaa);
glBindRenderbuffer(GL_RENDERBUFFER, fb->colorbuf_msaa);
glRenderbufferStorageMultisample(
GL_RENDERBUFFER, samples, GL_RGBA, width, height);
assert(glGetError() == GL_NO_ERROR);
glGenTextures(1, &fb->colorbuf);
glBindTexture(GL_TEXTURE_2D, fb->colorbuf);
glTexImage2D(GL_TEXTURE_2D,
0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
assert(glGetError() == GL_NO_ERROR);
GLuint fbo[2];
glGenFramebuffers(2, fbo);
fb->id_msaa = fbo[0];
fb->id = fbo[1];
glBindFramebuffer(GL_FRAMEBUFFER, fb->id_msaa);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fb->colorbuf_msaa);
assert(glGetError() == GL_NO_ERROR);
glBindFramebuffer(GL_FRAMEBUFFER, fb->id);
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->colorbuf, 0);
assert(glGetError() == GL_NO_ERROR);
}
void gleasy_framebuffer_deinitialize(gleasy_framebuffer_t* fb) {
assert(fb != NULL);
GLuint fbo[] = {fb->id_msaa, fb->id};
glDeleteFramebuffers(2, fbo);
glDeleteTextures(1, &fb->colorbuf);
glDeleteRenderbuffers(1, &fb->colorbuf_msaa);
}
void gleasy_framebuffer_bind(const gleasy_framebuffer_t* fb) {
assert(fb != NULL);
glBindFramebuffer(GL_FRAMEBUFFER, fb->id_msaa);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "gleasy: framebuffer is in invalid state\n");
abort();
}
}
void gleasy_framebuffer_flush(const gleasy_framebuffer_t* fb) {
assert(fb != NULL);
gleasy_framebuffer_flush_to_other(fb, fb->id);
}
void gleasy_framebuffer_flush_to_other(const gleasy_framebuffer_t* fb, GLuint id) {
assert(fb != NULL);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, id);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb->id_msaa);
glBlitFramebuffer(
0, 0, fb->width, fb->height,
0, 0, fb->width, fb->height,
GL_COLOR_BUFFER_BIT,
GL_NEAREST);
assert(glGetError() == GL_NO_ERROR);
}