PDA

View Full Version : [MRT] frame buffer object : target rendering



hibari
02-26-2015, 08:37 AM
Hi everyboby !

I have a problem with my code.
I want to use FBOs to send the rendering of my video to another fragment shader.
Here is my code.



#include "utils.h"

int width=512;
int height=512;

// perspective projection
bool perspective = false;

// geometry
#define _NBFACES 2 // 2 triangles

////////////////////////////////////////
// geometrical data
float points[_NBFACES * 3 * 3] = {
0.0f, (float)height, 0.0f, //1st triangle
(float)width, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, (float)height, -0.0f, //2nd triangle
(float)width, (float)height, -0.0f,
(float)width, 0.0f, -0.0f
};
float texCoords[_NBFACES * 3 * 2] = {
0.0f, (float)height, //1st triangle
(float)width, 0.0f,
0.0f, 0.0f,
0.0f, (float)height, //2nd triangle
(float)width, (float)height,
(float)width, 0.0f
};

// texture
cv::Mat image[2];
GLuint textureID[2];

// multipass
GLuint frameBufferId[4];
GLuint frameBufferTextureId[4];
GLuint drawBuffers[16] = {
GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3,
GL_COLOR_ATTACHMENT4,
GL_COLOR_ATTACHMENT5,
GL_COLOR_ATTACHMENT6,
GL_COLOR_ATTACHMENT7,
};

// shader variable pointers
GLint uniform_image_model;
GLint uniform_image_view;
GLint uniform_image_proj;
GLint uniform_video_texture;
//GLint uniform_mask_texture;
GLint uniform_nbFrames;

// shader variable pointers multipass
GLint uniform_writeFBO1_model;
GLint uniform_writeFBO1_view;
GLint uniform_writeFBO1_proj;
GLint uniform_writeFBO1_texture;
GLint uniform_writeFBO2_model;
GLint uniform_writeFBO2_view;
GLint uniform_writeFBO2_proj;
GLint uniform_writeFBO2_texture;
GLint uniform_writeFBO3_model;
GLint uniform_writeFBO3_view;
GLint uniform_writeFBO3_proj;
GLint uniform_writeFBO3_texture;
GLint uniform_writeFBO4_model;
GLint uniform_writeFBO4_view;
GLint uniform_writeFBO4_proj;
GLint uniform_writeFBO4_texture;

GLint uniform_writeFB04_texture_transfer;

GLint uniform_texture_FBO1;
GLint uniform_texture_FBO2;
GLint uniform_texture_FBO3;
GLint uniform_texture_FBO4;

GLint uniform_readFBO_model;
GLint uniform_readFBO_view;
GLint uniform_readFBO_proj;
GLint uniform_readFBO_video_texture;


/////////////////////////////////////////////
// FBO alloc
bool FBOInit( void ) {
int maxbuffers;
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxbuffers);
printf("Max attachments %d\n",maxbuffers);

glGenFramebuffers( 4, frameBufferId );

// attaching images to FBOs
for( int ind = 0 ; ind < 4 ; ind++ ) {
glBindFramebuffer( GL_FRAMEBUFFER, frameBufferId[ind] );

glGenTextures(1, frameBufferTextureId + ind);

glBindTexture(GL_TEXTURE_2D, frameBufferTextureId[ind]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTE R, GL_NEAREST);
glTexStorage2D(GL_TEXTURE_2D,1,GL_RGBA32F,width, height);
glFramebufferTexture2D( GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0 ,
GL_TEXTURE_2D,
frameBufferTextureId[ind] ,
0 );
if(glCheckFramebufferStatus(GL_FRAMEBUFFER)
==GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
printf("Error while Binding RECT FBO color %d texture No %d ID %d (error %d)\n" , frameBufferId[ind] , ind , frameBufferTextureId[ind] , glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
glDrawBuffers(1, drawBuffers);
glBindFramebuffer( GL_FRAMEBUFFER, 0 );

return true;
}



/////////////////////////////////////////////
// texture loading
bool loadtexture( string flieName , int index ) {
// texture load through OpenCV
image[index] = cv::imread( flieName, CV_LOAD_IMAGE_COLOR); // Read the file
if(! image[index].data ) { // Check for invalid input
printf( "Could not open or find the image\n" );
return false;
}
printf( "Loaded %s\n" , flieName.c_str() );
glEnable(GL_TEXTURE_2D);
glGenTextures( 1, &(textureID[index]) );
glActiveTexture (GL_TEXTURE0 + index);
glBindTexture( GL_TEXTURE_2D, (textureID[index]) );
glTexImage2D(GL_TEXTURE_2D, // Type of texture
0, // Pyramid level (for mip-mapping) - 0 is the top level
GL_RGB, // Internal colour format to convert to
image[index].cols, // Image width i.e. 640 for Kinect in standard mode
image[index].rows, // Image height i.e. 480 for Kinect in standard mode
0, // Border width in pixels (can either be 1 or 0)
GL_BGR, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.)
GL_UNSIGNED_BYTE, // Image data type
image[index].ptr()); // The actual image data itself
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTE R,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R,GL_LINEAR);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S , GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
// glGenerateMipmap(GL_TEXTURE_2D);
return true;
}

/////////////////////////////////////////////
// video frame texture initialization
bool initFrameTexture( IplImage *frame , int index ) {
glEnable(GL_TEXTURE_2D);
glGenTextures( 1, &(textureID[index]) );
glActiveTexture (GL_TEXTURE0 + index);
glBindTexture( GL_TEXTURE_2D, (textureID[index]) );
glTexImage2D(GL_TEXTURE_2D, // Type of texture
0, // Pyramid level (for mip-mapping) - 0 is the top level
GL_R16I, // Internal colour format to convert to
frame->width, // Image width i.e. 640 for Kinect in standard mode
frame->height, // Image height i.e. 480 for Kinect in standard mode
0, // Border width in pixels (can either be 1 or 0)
GL_BGR, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.)
GL_UNSIGNED_BYTE, // Image data type
frame->imageData); // The actual image data itself
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTE R,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R,GL_LINEAR);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S , GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
// glGenerateMipmap(GL_TEXTURE_2D);
return true;
}

////////////////////////////////////////
// main file
int main () {
// start GL context and O/S window using the GLFW helper library
if (!glfwInit ()) {
fprintf (stderr, "ERROR: could not start GLFW3\n");
return 1;
}

GLFWwindow* window
//= glfwCreateWindow (2*width, 2*height, "Hello Dice!", NULL, NULL);
= glfwCreateWindow (width, height, "Hello Dice!", NULL, NULL);
if (!window) {
fprintf (stderr, "ERROR: could not open window with GLFW3\n");
glfwTerminate();
return 1;
}
glfwMakeContextCurrent (window);

// Set key callback function
glfwSetErrorCallback(error_callback);
glfwSetKeyCallback(window, key_callback);
glfwSetCharCallback(window, char_callback);

// 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\n", renderer);
printf ("OpenGL version supported %s\n", 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"

// FBO init
FBOInit();

// video loading openCV
//Allocates and initializes cvCapture structure
// for reading a video stream from the camera.
//Index of camera is -1 since only one camera
// connected to the computer or it does not
// matter what camera to use.
//CvCapture *input_camera = cvCaptureFromCAM(-1);
CvCapture *input_camera = cvCaptureFromFile("/home/hibari/gpu_project/videos/toto.avi");
cvSetCaptureProperty(input_camera, CV_CAP_PROP_FPS, 1);


//Grabs and returns a frame from camera
IplImage *frame = NULL; //Preparing frame pointer
frame = cvQueryFrame(input_camera);
// texture loading
if( !frame ) {
printf("webcam frame not grabbed!\n");
return -1;
}
if( !initFrameTexture( frame , 0 ) ) {
return -1;
}

// texture loading
if( !loadtexture( "src/jup0vtt2-WB-640x480.png" , 1 ) ) {
return -1;
}

// vertex buffer objects and vertex array
unsigned int vbo = 0;
glGenBuffers (1, &vbo);
glBindBuffer (GL_ARRAY_BUFFER, vbo);
glBufferData (GL_ARRAY_BUFFER,
_NBFACES * 3 * 3 * sizeof (float),
points,
GL_STATIC_DRAW);
unsigned int vboTex = 0;
glGenBuffers (1, &vboTex);
glBindBuffer (GL_ARRAY_BUFFER, vboTex);
glBufferData (GL_ARRAY_BUFFER,
_NBFACES * 3 * 2 * sizeof (float),
texCoords,
GL_STATIC_DRAW);

unsigned int vao = 0;
glGenVertexArrays (1, &vao);
glBindVertexArray (vao);
glBindBuffer (GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte*)NULL);
glEnableVertexAttribArray (0);

// vertex positions are location 0
glBindBuffer (GL_ARRAY_BUFFER, vboTex);
glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 0, (GLubyte*)NULL);
glEnableVertexAttribArray (1); // don't forget this!


////////////////////////////////////////
// loading and compiling shaders
unsigned int vs_image = glCreateShader (GL_VERTEX_SHADER);
loadshader( "src/project_vs.glsl" , vs_image);
glCompileShader (vs_image);
printLog(vs_image);

unsigned int fs_image = glCreateShader (GL_FRAGMENT_SHADER);
loadshader( "src/project_fs.glsl" , fs_image);
glCompileShader (fs_image);
printLog(fs_image);

unsigned int shader_image_programme = glCreateProgram ();
glAttachShader (shader_image_programme, fs_image);
glAttachShader (shader_image_programme, vs_image);
glLinkProgram (shader_image_programme);

////////////////////////////////////////
// loading and compiling shaders
unsigned int vs_writeFBO1 = glCreateShader (GL_VERTEX_SHADER);
loadshader( "src/project_vs.glsl" , vs_writeFBO1);
glCompileShader (vs_writeFBO1);
printLog(vs_writeFBO1);

unsigned int vs_writeFBO2 = glCreateShader (GL_VERTEX_SHADER);
loadshader( "src/project_vs.glsl" , vs_writeFBO2);
glCompileShader (vs_writeFBO2);
printLog(vs_writeFBO2);

unsigned int vs_writeFBO3 = glCreateShader (GL_VERTEX_SHADER);
loadshader( "src/project_vs.glsl" , vs_writeFBO3);
glCompileShader (vs_writeFBO3);
printLog(vs_writeFBO3);

unsigned int vs_writeFBO4 = glCreateShader (GL_VERTEX_SHADER);
loadshader( "src/project_vs.glsl" , vs_writeFBO4);
glCompileShader (vs_writeFBO4);
printLog(vs_writeFBO4);

unsigned int vs_readFBO = glCreateShader (GL_VERTEX_SHADER);
loadshader( "src/project_vs.glsl" , vs_readFBO);
glCompileShader (vs_readFBO);
printLog(vs_readFBO);

unsigned int fs_writeFBO1 = glCreateShader (GL_FRAGMENT_SHADER);
loadshader( "src/project_fx1_fs.glsl" , fs_writeFBO1);
glCompileShader (fs_writeFBO1);
printLog(fs_writeFBO1);

unsigned int fs_writeFBO2 = glCreateShader (GL_FRAGMENT_SHADER);
loadshader( "src/project_fx2_fs.glsl" , fs_writeFBO2);
glCompileShader (fs_writeFBO2);
printLog(fs_writeFBO2);

unsigned int fs_writeFBO3 = glCreateShader (GL_FRAGMENT_SHADER);
loadshader( "src/project_fx3_fs.glsl" , fs_writeFBO3);
glCompileShader (fs_writeFBO3);
printLog(fs_writeFBO3);

unsigned int fs_writeFBO4 = glCreateShader (GL_FRAGMENT_SHADER);
loadshader( "src/project_fx4_fs.glsl" , fs_writeFBO4);
glCompileShader (fs_writeFBO4);
printLog(fs_writeFBO4);

unsigned int fs_readFBO = glCreateShader (GL_FRAGMENT_SHADER);
loadshader( "src/project_readfbo_fs.glsl" , fs_readFBO);
glCompileShader (fs_readFBO);
printLog(fs_readFBO);

unsigned int shader_writeFBO1_programme = glCreateProgram ();
glAttachShader (shader_writeFBO1_programme, fs_writeFBO1);
glAttachShader (shader_writeFBO1_programme, vs_writeFBO1);
glLinkProgram (shader_writeFBO1_programme);

unsigned int shader_writeFBO2_programme = glCreateProgram ();
glAttachShader (shader_writeFBO2_programme, fs_writeFBO2);
glAttachShader (shader_writeFBO2_programme, vs_writeFBO2);
glLinkProgram (shader_writeFBO2_programme);

unsigned int shader_writeFBO3_programme = glCreateProgram ();
glAttachShader (shader_writeFBO3_programme, fs_writeFBO3);
glAttachShader (shader_writeFBO3_programme, vs_writeFBO3);
glLinkProgram (shader_writeFBO3_programme);

unsigned int shader_writeFBO4_programme = glCreateProgram ();
glAttachShader (shader_writeFBO4_programme, fs_writeFBO4);
glAttachShader (shader_writeFBO4_programme, vs_writeFBO4);
glLinkProgram (shader_writeFBO4_programme);

unsigned int shader_readFBO_programme = glCreateProgram ();
glAttachShader (shader_readFBO_programme, fs_readFBO);
glAttachShader (shader_readFBO_programme, vs_readFBO);
glLinkProgram (shader_readFBO_programme);

////////////////////////////////////////
// shader parameeter bindings
uniform_image_model = glGetUniformLocation(shader_image_programme, "modelMatrix");
uniform_image_view = glGetUniformLocation(shader_image_programme, "viewMatrix");
uniform_image_proj = glGetUniformLocation(shader_image_programme, "projectionMatrix");
uniform_video_texture = glGetUniformLocation(shader_image_programme, "video");
uniform_nbFrames = glGetUniformLocation(shader_image_programme, "nbFrames");
if ( (uniform_image_proj == -1) || (uniform_image_view == -1)
|| (uniform_image_model == -1)
//|| (uniform_mask_texture == -1)
|| (uniform_video_texture == -1)
|| (uniform_nbFrames == -1)
) {
fprintf(stderr, "Could not bind uniforms image\n");
return 0;
}

////////////////////////////////////////
// shader parameeter bindings
uniform_readFBO_model = glGetUniformLocation(shader_readFBO_programme, "modelMatrix");
uniform_readFBO_view = glGetUniformLocation(shader_readFBO_programme, "viewMatrix");
uniform_readFBO_proj = glGetUniformLocation(shader_readFBO_programme, "projectionMatrix");
uniform_readFBO_video_texture = glGetUniformLocation(shader_readFBO_programme, "video");
uniform_texture_FBO1 = glGetUniformLocation(shader_readFBO_programme, "FBO1");
uniform_texture_FBO2 = glGetUniformLocation(shader_readFBO_programme, "FBO2");
uniform_texture_FBO3 = glGetUniformLocation(shader_readFBO_programme, "FBO3");
uniform_texture_FBO4 = glGetUniformLocation(shader_readFBO_programme, "FBO4");
if ( (uniform_readFBO_proj == -1) || (uniform_readFBO_view == -1)
|| (uniform_readFBO_model == -1)
|| (uniform_texture_FBO1 == -1)
|| (uniform_texture_FBO2 == -1)
|| (uniform_texture_FBO3 == -1)
|| (uniform_texture_FBO4 == -1)
) {
fprintf(stderr, "Could not bind uniforms readFBO\n");
// return 0;
}

////////////////////////////////////////
// endless rendering loop
int nbFrames = 0;
while (!glfwWindowShouldClose (window)) {

// projection matrix
glm::mat4 projectionMatrix; // Store the projection matrix
glm::mat4 viewMatrix; // Store the view matrix
glm::mat4 modelMatrix; // Store the model matrix

// Projection: Ortho matrix
projectionMatrix
= glm::ortho(0.0f,(float)width,(float)height,0.0f);

// Camera matrix
viewMatrix = glm::mat4(1.0f);

// Model matrix : an identity matrix (model will be at the origin)
modelMatrix = glm::mat4(1.0f);


//////////////////////////////////////////////////
// PASS #1
// output buffer cleanup
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferId[0]);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

////////////////////////////////////////
// activate shaders and sets uniform variable values
glUseProgram(shader_image_programme);
glBindVertexArray (vao);
glUniformMatrix4fv(uniform_image_proj, 1, GL_FALSE,
glm::value_ptr(projectionMatrix));
glUniformMatrix4fv(uniform_image_view, 1, GL_FALSE,
glm::value_ptr(viewMatrix));
glUniformMatrix4fv(uniform_image_model, 1, GL_FALSE,
glm::value_ptr(modelMatrix));

glUniform1i(uniform_video_texture, 0); //Texture unit 1

glUniform1i(uniform_nbFrames, nbFrames);

// input texture (loaded texture)
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, textureID[0]);

// frame capture
frame = cvQueryFrame(input_camera);
glTexImage2D(GL_TEXTURE_2D, // Type of texture
0, // Pyramid level (for mip-mapping) - 0 is the top level
GL_RGB, // Internal colour format to convert to
frame->width, // Image width i.e. 640 for Kinect in standard mode
frame->height, // Image height i.e. 480 for Kinect in standard mode
0, // Border width in pixels (can either be 1 or 0)
GL_BGR, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.)
GL_UNSIGNED_BYTE, // Image data type
frame->imageData); // The actual image data itself

// draw points from the currently bound VAO with current in-use shader
glDrawArrays (GL_TRIANGLES, 0, _NBFACES * 3);

//glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBufferId[0]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

////////////////////////////////////////
// activate shaders and sets uniform variable values
glUseProgram (shader_readFBO_programme);
glBindVertexArray (vao);
glUniformMatrix4fv(uniform_readFBO_proj, 1, GL_FALSE,
glm::value_ptr(projectionMatrix));
glUniformMatrix4fv(uniform_readFBO_view, 1, GL_FALSE,
glm::value_ptr(viewMatrix));
glUniformMatrix4fv(uniform_readFBO_model, 1, GL_FALSE,
glm::value_ptr(modelMatrix));

glUniform1i(uniform_readFBO_video_texture, 0); //Texture unit 1

// input texture (loaded texture)
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, frameBufferId[0]);

// draw points from the currently bound VAO with current in-use shader
glDrawArrays (GL_TRIANGLES, 0, _NBFACES * 3);

///////////////////////////////////////
// EVENTS + FB swap

// update other events like input handling
glfwPollEvents ();

// put the stuff we've been drawing onto the display
glfwSwapBuffers (window);

nbFrames++;
}


//Release cvCapture structure
cvReleaseCapture(&input_camera);

// close GL context and any other GLFW resources
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}



Here is a pastebin because the line numbers are not displayed with the "code" tags :
pastebin.com/GLxwYjpT

My problem is on the lines 433-434 and 472-473.
For the first pass i'm using :


glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferId[0]);

and for the second pass :


glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBufferId[0]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);


Despite of that, i have a black screen.
Can someone tell what i did wrong ? It would be nice.

Thanks everybody.

Alfonse Reinheart
02-26-2015, 09:37 AM
The read framebuffer (https://www.opengl.org/wiki/Framebuffer#Bind_points) is for operations that read from the framebuffer itself. Fragment shaders cannot read from a framebuffer; they can read from textures.

So you need to bind the texture that was previously written to.

hibari
02-26-2015, 01:26 PM
A thousand of thanks Mr. Reinheart. I spent the all day on it without seeing this mistake (beginners).

To sum up, i had to replace


glBindTexture(GL_TEXTURE_2D, frameBufferId[0];

by


glBindTexture(GL_TEXTURE_2D, frameBufferTextureId[0];


Thanks again !

hibari
02-26-2015, 01:30 PM
How can i mark my thread as solved ?