-
Notifications
You must be signed in to change notification settings - Fork 0
/
fbo.cpp
172 lines (136 loc) · 5.33 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
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#include <iostream>
#include "fbo.h"
#include <png.h>
bool alpha_save = true;
int image_width = 1024, image_height = 1024;
GLuint framebuffer;
GLuint status;
void ExternalRenderer::setImageWidth(int width) {
image_width = width;
}
void ExternalRenderer::setImageHeight(int height) {
image_height = height;
}
void ExternalRenderer::switchToExternalTarget() {
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
}
void ExternalRenderer::switchToWindowTarget() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void ExternalRenderer::getNewRenderBuffer(GLuint *buffer) {
glGenRenderbuffers(1, buffer);
glBindRenderbuffer(GL_RENDERBUFFER, *buffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, image_width, image_height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *buffer);
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "Error while attaching new render buffer:\n");
#ifndef __MAC__
printFrameBufferError();
#endif
exit(0);
}
}
void ExternalRenderer::deleteRenderBuffer(GLuint *renderbuffer) {
glDeleteRenderbuffers(1, renderbuffer);
}
void ExternalRenderer::outputToImage(string name) {
string filename = name + ".png";
cout << "saving img to " << filename << endl;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
int bytes = image_width*image_height*(alpha_save ? 4 : 3); //Color space is RGBA
GLubyte *buffer = (GLubyte *)malloc(bytes);
glReadPixels(0, 0, image_width, image_height, (alpha_save ? GL_RGBA : GL_RGB),
GL_UNSIGNED_BYTE, buffer);
saveToPNG(filename, buffer);
free(buffer);
}
void PNGWriteData(png_structp png_ptr, png_bytep data, png_size_t length) {
FILE* fp = (FILE*) png_get_io_ptr(png_ptr);
fwrite((void*) data, 1, length, fp);
}
bool saveToPNG(string filename, GLubyte *buffer) {
FILE* out;
out = fopen(filename.c_str(), "wb");
if (out == NULL) {
cout << "Can't open screen capture file " << filename.c_str() << endl;
return false;
}
int rowStride = (alpha_save ? image_width * 4
: (image_width * 3 + 3) & ~0x3);
png_bytep* row_pointers = new png_bytep[image_height];
for (int i = 0; i < image_height; i++)
row_pointers[i] = (png_bytep) &buffer[rowStride * (image_height - i - 1)];
png_structp png_ptr;
png_infop info_ptr;
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL);
if (png_ptr == NULL) {
cout << "Screen capture: error allocating png_ptr" << endl;
fclose(out);
return false;
}
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
cout << "Screen capture: error allocating info_ptr" << endl;
fclose(out);
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
return false;
}
png_set_write_fn(png_ptr, (void*) out, PNGWriteData, NULL);
png_set_compression_level(png_ptr, 5);
png_set_IHDR(png_ptr, info_ptr,
image_width, image_height,
8,
(alpha_save ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB),
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
png_write_info(png_ptr, info_ptr);
png_write_image(png_ptr, row_pointers);
png_write_end(png_ptr, info_ptr);
cout << "saved to " + filename << endl;
// Clean up everything . . .
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(out);
}
#ifndef __APPLE__
void printFrameBufferError() {
switch(status) {
case GL_FRAMEBUFFER_COMPLETE:
return;
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
cout << "An attachment could not be bound to frame buffer object!" << endl;
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
cout << "Attachments are missing! At least one image (texture) must be bound to the frame buffer object!" << endl;
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
cout << "The dimensions of the buffers attached to the currently used frame buffer object do not match!" << endl;
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
cout << "The formats of the currently used frame buffer object are not supported or do not fit together!" << endl;
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
cout << "A Draw buffer is incomplete or undefinied. All draw buffers must specify attachment points that have images attached." << endl;
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
cout << "A Read buffer is incomplete or undefinied. All read buffers must specify attachment points that have images attached." << endl;
break;
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
cout << "All images must have the same number of multisample samples." << endl;
break;
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS :
cout << "If a layered image is attached to one attachment, then all attachments must be layered attachments. The attached layers do not have to have the same number of layers, nor do the layers have to come from the same kind of texture." << endl;;
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
cout << "Attempt to use an unsupported format combinaton!" << endl;
break;
default:
cout << "Unknown error while attempting to create frame buffer object!" << endl;
break;
}
}
#endif