Hi all, I would like to use the color method for picking with a separate FBO. I have run into the problem that, even though AFAICT I have setup the FBO identically to the default framebuffer, which renders fine, the underlying FBO rendering is not correct.
In an attempt to make a MWE, I ran into another problem where my simple triangle renders white instead of colored. I am not particularly concerned with this issue, but really I am wondering if the workflow I am employing is sensible and if there are any obvious problems. Thank you for your help.
The boilerplate from an existing simple triangle example:
#include <iostream>
#include <vector>
#include <GL/glew.h> // include GLEW and new version of GL on Windows
#include <GLFW/glfw3.h> // GLFW helper library
#include <stdio.h>
int main() {
// start GL context and O/S window using the GLFW helper library
if (!glfwInit()) {
fprintf(stderr, "ERROR: could not start GLFW3
");
return 1;
}
int width = 640;
int height = 480;
GLFWwindow* window = glfwCreateWindow(width, height, "Hello Triangle", NULL, NULL);
if (!window) {
fprintf(stderr, "ERROR: could not open window with GLFW3
");
glfwTerminate();
return 1;
}
glfwMakeContextCurrent(window);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
const GLubyte* version = glGetString(GL_VERSION); // version as a string
printf("Renderer: %s
", renderer);
printf("OpenGL version supported %s
", version);
// tell GL to only draw onto a pixel if the shape is closer to the viewer
glEnable(GL_DEPTH_TEST); // enable depth-testing
glDepthFunc(GL_LESS); // depth-testing interprets a smaller value as "closer"
glDepthMask(GL_TRUE); // Enable depth test (z-buffer)
The FBO, VAO, and Program setup:
////////////////// Setup VBO ///////////////////
float points[] = {
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f
};
uint8_t colors[] = {
100, 100, 0,
100, 100, 0,
100, 100, 0
};
uint8_t colors_fbo[] = {
100, 0, 100,
100, 0, 100,
100, 0, 100
};
uint32_t indices[] = {0, 1, 2}; // one triangle
GLuint vao = 0;
std::vector<GLuint> vbos;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
vbos.resize(3); // xyz, colors, indices
glGenBuffers(3, vbos.data());
glBindBuffer(GL_ARRAY_BUFFER, vbos[0]);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), points, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, vbos[1]);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(uint8_t), colors, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * sizeof(uint32_t), indices, GL_STATIC_DRAW);
// glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
/////////////////////////////////////////
//////////////////// Setup FBO //////////
GLuint fbo = 0;
GLuint color = 0;
GLuint depth = 0;
GLuint fbo_vao = 0;
std::vector<GLuint> fbo_vbos;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenTextures(1, &color);
glBindTexture(GL_TEXTURE_2D, color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
color, 0);
glGenRenderbuffers(1, &depth);
glBindRenderbuffer(GL_RENDERBUFFER, depth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE){
std::cerr<<"Framebuffer fail, :"<<status<<std::endl;
}
// same points, different colors
glGenVertexArrays(1, &fbo_vao);
glBindVertexArray(fbo_vao);
fbo_vbos.resize(3);
glGenBuffers(3, fbo_vbos.data());
glBindBuffer(GL_ARRAY_BUFFER, fbo_vbos[0]);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), points, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, fbo_vbos[1]);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(uint8_t), colors_fbo, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, fbo_vbos[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * sizeof(uint32_t), indices, GL_STATIC_DRAW);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
////////////////////////////////////////
/////////////////// Setup Program ///////
const char* vertex_shader =
"#version 330 core
"
"layout (location = 0) in vec3 position;"
"layout (location = 1) in vec3 color;"
"flat out vec3 vColor;"
"void main() {"
" vColor = color;"
" gl_Position = vec4(vp, 1.0);"
"}";
const char* fragment_shader =
"#version 330 core
"
"flat in vec3 vColor;"
"out vec4 fColor;"
"void main() {"
" fColor = vec4(vColor, 1.0f);"
"}";
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertex_shader, NULL);
glCompileShader(vs);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragment_shader, NULL);
glCompileShader(fs);
GLuint shader_programme = glCreateProgram();
glAttachShader(shader_programme, fs);
glAttachShader(shader_programme, vs);
glLinkProgram(shader_programme);
///////////////////////////////////////////
The render loop:
float pixel_value[3];
while(!glfwWindowShouldClose(window)) {
// wipe the drawing surface clear
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_programme);
// write to, read from default buffer
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
glReadPixels(320, 240, 1, 1, GL_RGB, GL_FLOAT, pixel_value);
std::cout<<" Pixel value default buffer: "<<pixel_value[0]<<" "<<pixel_value[1]<<" "<<pixel_value[2]<<std::endl;
glBindVertexArray(0);
// write to, read from fbo
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glBindVertexArray(fbo_vao);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
glReadPixels(320, 240, 1, 1, GL_RGB, GL_FLOAT, pixel_value);
std::cout<<" Pixel value fbo: "<<pixel_value[0]<<" "<<pixel_value[1]<<" "<<pixel_value[2]<<std::endl;
glBindVertexArray(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glfwPollEvents();
// put the stuff we've been drawing onto the display
glfwSwapBuffers(window);
}
// close GL context and any other GLFW resources
glfwTerminate();
return 0;
}
Simple makefile:
OBJS = fbo_mwe.o
minimalfbo: $(OBJS)
$(CC) -o fbo_mwe $(OBJS) -lm -lGL -lGLU -lGLEW -lglut -lglfw -lstdc++