-
Notifications
You must be signed in to change notification settings - Fork 0
/
fbo.cpp
111 lines (90 loc) · 3.74 KB
/
fbo.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "fbo.h"
#include "image.h"
#include "queue.h"
#include "shader.h"
#include "lib/GLAD/glad.h"
#include "lib/util/vec.h"
#include "lib/util/io.h"
struct framebuffer {
GLuint fbo, rbo, tex;
};
static GLuint activefbo = 0;
static Image activefboimg = LIBDRAW_CONST(SCREEN);
static vector<framebuffer> fbos;
GLuint createfbo(Image image) {
ImageMeta& meta = findimg(image);
GLuint fbo = 0, rbo = 0;
glGenFramebuffers(1, &fbo);
glGenRenderbuffers(1, &rbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, meta.id, 0);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, meta.w, meta.h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
if (GLenum err = glGetError()) println("Failed to create renderbuffer: ", (int)err);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
println("Framebuffer is incomplete: ", (int)glCheckFramebufferStatus(GL_FRAMEBUFFER));
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
fbos.push({ fbo, rbo, meta.id });
return fbo;
}
void bindfbo(Image image) {
activefboimg = image;
ImageMeta* meta = &findimg(image);
Image id = image;
while (meta->parent > 0) id = meta->parent, meta = &findimg(meta->parent);
GLuint fbo = 0;
if (meta->parent < 0) fbo = -meta->parent;
else fbo = -(meta->parent = -(int)createfbo({ id }));
if (activefbo != fbo) {
activefbo = fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
int width = meta->w, height = meta->h;
apply_default_uniforms();
glViewport(0, 0, width, height);
glClearColor(0, 0, 0, 0);
ensure3d();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// bindtexture({ 0 });
}
}
Image currentfbo() {
return activefboimg;
}
void unbindfbo() {
if (activefbo != 0) {
activefbo = 0;
activefboimg = SCREEN;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
apply_default_uniforms();
glViewport(0, 0, findimg(1).w, findimg(1).h); // image 1 is default fbo
glClearColor(0, 0, 0, 0);
ensure3d();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
}
ImageMeta init_default_fbo(int width, int height) {
GLuint fbtex, fbo, rbo;
glGenTextures(1, &fbtex);
glGenFramebuffers(1, &fbo);
glGenRenderbuffers(1, &rbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glBindTexture(GL_TEXTURE_2D, fbtex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbtex, 0);
if (GLenum err = glGetError()) println("Failed to create default framebuffer texture: ", (int)err);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
if (GLenum err = glGetError()) println("Failed to create default renderbuffer: ", (int)err);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
fbos.push({ fbo, rbo, fbtex });
return { 0, 0, width, height, fbtex, { -int(fbo) } };
}