I'm using OpenGL to create a scene, render it and apply a motion blur post process to it.
I have a temporary frame to initially render the scene to and 2 other frames that are used in the post processing - A current frame, and a previous frame.
The current frame and previous frame are flipped each time the render method is called, i.e. Frame 0: current = 0, previous = 1. Frame 2: current = 1, previous = 0.
The render method is as follows:
First I set my render target to the temp frame with
glBindFrameBuffer
.
Then I clear the frame and render the scene to it.
Next I set the render target to the current frame, clear that and bind the motion blur effect with glUseProgram
. Then I'm sending a 4x4 identity matrix to the shader as a uniform for the model-view-projection matrix of the quad that is rendered to the screen (just like with all post processing methods).
Then - now this is the bit I think is going wrong - I bind 2 textures using glActiveTexture(GL_TEXTURE0 + index)
and glBindTexture
(from glew). These are the temp frame texture and the previous frame texture.
Afterwards, I send a blend factor to the shader, used in a mix operation between the 2 textures I just sent. Then I render to the screen quad.
Finally, I set the the render target to the screen, bind the (ultimate) texture effect, send the identity matrix, bind the current frame texture to it and render it to the screen quad once more.
The scene does render but without motion blur.
Could it be that nothing is going into the previous frame? I thought this might be the case, so I tested it in the motion blur shader by subtracting one texture from the other. The result was a black screen (I tested both ways). So this means that the 2 textures are the same, right? I moved the camera around, so it should at least flicker if they weren't. I even reduced the fps by adding a Sleep
to the update method, same result.
Any help is appreciated, thanks.
The code in main:
bool render()
{
// !!!!!!!!!!!!!!! FIRST PASS !!!!!!!!!!!!!!!!
unsigned int previous_frame = ((current_frame) == 1) ? 0 : 1;
// *******************************
// Set render target to temp frame
// *******************************
renderer::set_render_target(temp_frame);
// ***********
// Clear frame
// ***********
renderer::clear();
// Render meshes
for (auto &e : meshes)
{
auto m = e.second;
// Bind effect
renderer::bind(eff);
// Create MVP matrix
auto M = m.get_transform().get_transform_matrix();
auto V = cam.get_view();
auto P = cam.get_projection();
auto MVP = P * V * M;
// Set MVP matrix uniform
glUniformMatrix4fv(
eff.get_uniform_location("MVP"), // Location of uniform
1, // Number of values - 1 mat4
GL_FALSE, // Transpose the matrix?
value_ptr(MVP)); // Pointer to matrix data
// Create MV matrix
auto MV = V * M;
// Set MV matrix uniform
glUniformMatrix4fv(
eff.get_uniform_location("MV"), // Location of uniform
1, // Number of values - 1 mat4
GL_FALSE, // Transpose the matrix?
value_ptr(MV)); // Pointer to matrix data
// Set M matrix uniform
glUniformMatrix4fv(
eff.get_uniform_location("M"),
1,
GL_FALSE,
value_ptr(M));
// Set N matrix uniform
glUniformMatrix3fv(
eff.get_uniform_location("N"),
1,
GL_FALSE,
value_ptr(m.get_transform().get_normal_matrix()));
// Bind material
renderer::bind(m.get_material(), "mat");
// Bind light
renderer::bind(light, "light");
// Bind texture
renderer::bind(tex, 0);
// Set tex uniform
glUniform1i(eff.get_uniform_location("tex"), 0);
// Set eye position
glUniform3fv(eff.get_uniform_location("eye_pos"), 1, value_ptr(cam.get_position()));
// Render mesh
renderer::render(m);
}
// !!!!!!!!!!!!!!! SECOND PASS !!!!!!!!!!!!!!!!
// **********************************
// Set render target to current frame
// **********************************
renderer::set_render_target(frames[current_frame]);
// ***********
// Clear frame
// ***********
renderer::clear();
// ***********************
// Bind motion blur effect
// ***********************
renderer::bind(motion_blur);
// ******************************
// MVP is now the identity matrix
// ******************************
auto MVP = ident;
glUniformMatrix4fv(motion_blur.get_uniform_location("MVP"), 1, GL_FALSE, value_ptr(MVP));
// ***********
// Bind frames
// ***********
renderer::bind(temp_frame.get_frame(), 0);
renderer::bind(frames[previous_frame].get_frame(), 1);
// ****************
// Set blend factor
// ****************
float blend_factor = 0.5;
glUniform1f(motion_blur.get_uniform_location("blend_factor"), blend_factor);
// ******************
// Render screen quad
// ******************
renderer::render(screen_quad);
// !!!!!!!!!!!!!!! SCREEN PASS !!!!!!!!!!!!!!!!
// ************************************
// Set render target back to the screen
// ************************************
renderer::set_render_target();
// Use texturing effect
renderer::bind(tex_eff);
// **********************
// Set MVP matrix uniform (Model View Projection, now identity)
// **********************
glUniformMatrix4fv(tex_eff.get_uniform_location("MVP"), 1, GL_FALSE, value_ptr(MVP));
// ******************************
// Bind texture from frame buffer
// ******************************
renderer::bind(frames[current_frame].get_frame(), 0);
// **********************
// Render the screen quad
// **********************
renderer::render(screen_quad);
return true;
}
The code in my motion blur shader:
#version 410
// Current frame being rendered
uniform sampler2D tex;
// Previous frame
uniform sampler2D previous_frame;
// Blend factor between frames
uniform float blend_factor;
// Incoming texture coordinate
layout (location = 0) in vec2 tex_coord;
// Outgoing colour
layout (location = 0) out vec4 colour;
void main()
{
vec4 out_colour;
// ***********************
// Sample the two textures
// ***********************
vec4 current = texture(tex, tex_coord);
vec4 previous = texture(previous_frame, tex_coord);
// *****************************
// Mix between these two colours
// *****************************
out_colour = mix(current, previous, blend_factor);
// *******************
// Ensure alpha is 1.0
// *******************
out_colour.w = 1.0;
colour = out_colour;
}
Aucun commentaire:
Enregistrer un commentaire