forked from drahosp/ppgso
-
Notifications
You must be signed in to change notification settings - Fork 5
/
gl8_framebuffer.cpp
150 lines (120 loc) · 5.12 KB
/
gl8_framebuffer.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Example gl_framebuffer
// - Demonstrates use of Framebuffer Object (FBO)
// - Renders a scene to a texture in graphics memory and uses this texture in the final scene displayed on screen
#include <iostream>
#include <cmath>
#include <glm/glm.hpp>
#include <ppgso/ppgso.h>
#include <shaders/convolution_vert_glsl.h>
#include <shaders/convolution_frag_glsl.h>
#include <shaders/texture_vert_glsl.h>
#include <shaders/texture_frag_glsl.h>
const unsigned int SIZE = 512;
/*!
* Custom window for displaying FBO object
*/
class FramebufferWindow : public ppgso::Window {
private:
// Objects to be rendered into the framebuffer
ppgso::Shader sphereShader = {texture_vert_glsl, texture_frag_glsl};
ppgso::Mesh sphereMesh = {"sphere.obj"};
ppgso::Texture sphereTexture = {ppgso::image::loadBMP("sphere.bmp")};
// Objects to render the framebuffer on to
ppgso::Shader quadShader = {convolution_vert_glsl, convolution_frag_glsl};
ppgso::Mesh quadMesh = {"quad.obj"};
ppgso::Texture quadTexture = {SIZE, SIZE};
// OpenGL object ids for framebuffer and render buffer
GLuint fbo = 0;
GLuint rbo = 0;
public:
/*!
* Constructor for our custom window
*/
FramebufferWindow() : Window{"gl8_framebuffer", SIZE, SIZE} {
// Set up OpenGL options
// Enable Z-buffer
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
// Disable mipmapping on the quadTexture
quadTexture.bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// Initialize framebuffer, its color texture (the sphere will be rendered to it) and its render buffer for depth info storage
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// Set up render buffer that has a depth buffer and stencil buffer
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
// Associate the quadTexture with it
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, quadTexture.image.width, quadTexture.image.height);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, quadTexture.getTexture(), 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
throw std::runtime_error("Cannot create framebuffer!");
}
}
/*!
* Free any allocated OpenGL resources
*/
~FramebufferWindow() override {
glDeleteRenderbuffers(1, &rbo);
glDeleteFramebuffers(1, &fbo);
}
/*!
* Window update implementation that will be called automatically from pollEvents
*/
void onIdle() override {
auto time = (float) glfwGetTime();
// --------
// Pass 1 - Render a scene with sphere to a texture in graphics memory
// --------
// Set rendering target to texture
glViewport(0, 0, SIZE, SIZE);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// Clear the framebuffer
glClearColor(.5f, .7f, .5f, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Create projection matrix (field of view (radians), aspect ratio, near plane distance, far plane distance)
auto sphereProjectionMatrix = glm::perspective((ppgso::PI / 180.f) * 60.0f, (float)SIZE/(float)SIZE, 1.0f, 10.0f);
// Create view matrix (translate camera backwards a bit, so we can see the geometry)
auto sphereViewMatrix = glm::translate(glm::mat4{1.0}, {0.0f, 0.0f, -1.5f});
// Assign sphere texture
auto sphereModelMatrix = glm::rotate(glm::mat4{1.0f}, time, {0, 1, 0});
// Set shader inputs
sphereShader.use();
sphereShader.setUniform("ProjectionMatrix", sphereProjectionMatrix);
sphereShader.setUniform("ViewMatrix", sphereViewMatrix);
sphereShader.setUniform("ModelMatrix", sphereModelMatrix);
sphereShader.setUniform("Texture", sphereTexture);
sphereMesh.render();
// --------
// Pass 2 - Render the final scene to screen
// --------
// Set rendering target to screen
resetViewport();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Clear the framebuffer
glClearColor(.2f, .2f, .2f, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Create projection matrix (field of view (radians), aspect ratio, near plane distance, far plane distance)
auto quadProjectionMatrix = glm::perspective((ppgso::PI / 180.f) * 60.0f, (float)SIZE/(float)SIZE, 1.0f, 10.0f);
// Create view matrix (translate camera backwards a bit, so we can see the geometry)
auto quadViewMatrix = glm::translate(glm::mat4{1.0f}, {0.0f, 0.0f, -3.0f});
// Animate rotation of the quad
auto quadModelMatrix = glm::rotate(glm::mat4{1.0f}, sinf(time / 2.0f) * 1.5f, {0, 1, .1});
// Set shader inputs
quadShader.use();
quadShader.setUniform("ProjectionMatrix", quadProjectionMatrix);
quadShader.setUniform("ViewMatrix", quadViewMatrix);
quadShader.setUniform("ModelMatrix", quadModelMatrix);
quadShader.setUniform("Texture", quadTexture);
quadMesh.render();
}
};
int main() {
// Create our custom window
FramebufferWindow window;
// Main execution loop
while (window.pollEvents()) {}
return EXIT_SUCCESS;
}