Turn motion blur into camera space motion blur
This commit is contained in:
parent
de7ceb0c2d
commit
f23f7b05e5
@ -25,20 +25,17 @@ uniform float boost_amount;
|
||||
|
||||
// The color buffer to use.
|
||||
uniform sampler2D color_buffer;
|
||||
uniform sampler2D dtex;
|
||||
|
||||
// Center (in texture coordinates) at which the kart is. A small circle
|
||||
// around this center is not blurred (see mask_radius below)
|
||||
uniform vec2 center;
|
||||
|
||||
// The direction to which the blurring aims at
|
||||
uniform vec2 direction;
|
||||
|
||||
// Radius of mask around the character in which no blurring happens
|
||||
// so that the kart doesn't get blurred.
|
||||
uniform float mask_radius;
|
||||
|
||||
// Maximum height of texture used
|
||||
uniform float max_tex_height;
|
||||
uniform mat4 previous_viewproj;
|
||||
|
||||
layout (std140) uniform MatrixesData
|
||||
{
|
||||
@ -55,42 +52,44 @@ out vec4 FragColor;
|
||||
// Number of samples used for blurring
|
||||
#define NB_SAMPLES 8
|
||||
|
||||
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texcoords = gl_FragCoord.xy / screen;
|
||||
vec2 texcoords = gl_FragCoord.xy / screen;
|
||||
|
||||
// Sample the color buffer
|
||||
vec3 color = texture(color_buffer, texcoords).rgb;
|
||||
// Sample the color buffer
|
||||
vec3 color = texture(color_buffer, texcoords).rgb;
|
||||
|
||||
// Compute the blur direction.
|
||||
// IMPORTANT: we don't normalize it so that it avoids a glitch around 'center',
|
||||
// plus it naturally scales the motion blur in a cool way :)
|
||||
vec2 blur_dir = direction - texcoords;
|
||||
float z = texture(dtex, texcoords).x;
|
||||
vec4 ViewPos = getPosFromUVDepth(vec3(texcoords, z), InverseProjectionMatrix);
|
||||
vec4 OldScreenPos = previous_viewproj * InverseViewMatrix * ViewPos;
|
||||
OldScreenPos /= OldScreenPos.w;
|
||||
OldScreenPos = .5 * OldScreenPos + .5;
|
||||
|
||||
// Compute the blurring factor:
|
||||
// - apply the mask, i.e. no blurring in a small circle around the kart
|
||||
float blur_factor = max(0.0, length(texcoords - center) - mask_radius);
|
||||
// Compute the blur direction.
|
||||
// IMPORTANT: we don't normalize it so that it avoids a glitch around 'center',
|
||||
// plus it naturally scales the motion blur in a cool way :)
|
||||
vec2 blur_dir = texcoords - OldScreenPos.xy;
|
||||
|
||||
// - avoid blurring the top of the screen
|
||||
blur_factor *= (max_tex_height - texcoords.t);
|
||||
// Compute the blurring factor:
|
||||
// - apply the mask, i.e. no blurring in a small circle around the kart
|
||||
float blur_factor = max(0.0, length(texcoords - center) - mask_radius);
|
||||
|
||||
// - apply the boost amount
|
||||
blur_factor *= boost_amount;
|
||||
// - apply the boost amount
|
||||
blur_factor *= boost_amount;
|
||||
|
||||
// Scale the blur direction
|
||||
blur_dir *= blur_factor;
|
||||
// Scale the blur direction
|
||||
blur_dir *= blur_factor;
|
||||
|
||||
// Compute the blur
|
||||
vec2 inc_vec = blur_dir / vec2(NB_SAMPLES);
|
||||
vec2 blur_texcoords = texcoords + inc_vec;
|
||||
for(int i=1 ; i < NB_SAMPLES ; i++)
|
||||
{
|
||||
color += texture(color_buffer, blur_texcoords).rgb;
|
||||
blur_texcoords += inc_vec;
|
||||
}
|
||||
color /= vec3(NB_SAMPLES);
|
||||
FragColor = vec4(color, 1.0);
|
||||
|
||||
// Keep this commented line for debugging:
|
||||
//FragColor = vec4(blur_factor, blur_factor, blur_factor, 0.0);
|
||||
// Compute the blur
|
||||
vec2 inc_vec = blur_dir / vec2(NB_SAMPLES);
|
||||
vec2 blur_texcoords = texcoords + inc_vec;
|
||||
for(int i=1 ; i < NB_SAMPLES ; i++)
|
||||
{
|
||||
color += texture(color_buffer, blur_texcoords).rgb;
|
||||
blur_texcoords += inc_vec;
|
||||
}
|
||||
color /= vec3(NB_SAMPLES);
|
||||
FragColor = vec4(color, 1.0);
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ private:
|
||||
core::array<video::IRenderTarget> m_mrt;
|
||||
|
||||
/** Matrixes used in several places stored here to avoid recomputation. */
|
||||
core::matrix4 m_ViewMatrix, m_InvViewMatrix, m_ProjMatrix, m_InvProjMatrix, m_ProjViewMatrix, m_InvProjViewMatrix;
|
||||
core::matrix4 m_ViewMatrix, m_InvViewMatrix, m_ProjMatrix, m_InvProjMatrix, m_ProjViewMatrix, m_previousProjViewMatrix, m_InvProjViewMatrix;
|
||||
|
||||
std::vector<video::ITexture *> SkyboxTextures;
|
||||
std::vector<video::ITexture *> SphericalHarmonicsTextures;
|
||||
@ -694,7 +694,8 @@ public:
|
||||
void setProjMatrix(core::matrix4 matrix) { m_ProjMatrix = matrix; matrix.getInverse(m_InvProjMatrix); }
|
||||
const core::matrix4 &getProjMatrix() const { return m_ProjMatrix; }
|
||||
const core::matrix4 &getInvProjMatrix() const { return m_InvProjMatrix; }
|
||||
void genProjViewMatrix() { m_ProjViewMatrix = m_ProjMatrix * m_ViewMatrix; m_InvProjViewMatrix = m_ProjViewMatrix; m_InvProjViewMatrix.makeInverse(); }
|
||||
void genProjViewMatrix() { m_previousProjViewMatrix = m_ProjViewMatrix; m_ProjViewMatrix = m_ProjMatrix * m_ViewMatrix; m_InvProjViewMatrix = m_ProjViewMatrix; m_InvProjViewMatrix.makeInverse(); }
|
||||
const core::matrix4 & getPreviousPVMatrix() { return m_previousProjViewMatrix; }
|
||||
const core::matrix4 &getProjViewMatrix() const { return m_ProjViewMatrix; }
|
||||
const core::matrix4 &getInvProjViewMatrix() const { return m_InvProjViewMatrix; }
|
||||
#ifdef DEBUG
|
||||
|
@ -610,10 +610,14 @@ void PostProcessing::renderMotionBlur(unsigned cam, FrameBuffer &in_fbo, FrameBu
|
||||
setTexture(0, in_fbo.getRTT()[0], GL_NEAREST, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
setTexture(1, irr_driver->getDepthStencilTexture(), GL_NEAREST, GL_NEAREST);
|
||||
FullScreenShader::MotionBlurShader
|
||||
::setUniforms(cb->getBoostTime(cam), cb->getCenter(cam),
|
||||
::setUniforms(1., // Todo : should be framerate dependent
|
||||
// Todo : use a previousPVMatrix per cam, not global
|
||||
irr_driver->getPreviousPVMatrix(),
|
||||
cb->getCenter(cam),
|
||||
cb->getDirection(cam), 0.15f,
|
||||
cb->getMaxHeight(cam) * 0.7f, 0);
|
||||
cb->getMaxHeight(cam) * 0.7f, 0, 1);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
}
|
||||
@ -868,7 +872,7 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode, boo
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Motion blur", 0xFF, 0x00, 0x00);
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_MOTIONBLUR));
|
||||
if (isRace && UserConfigParams::m_motionblur && m_any_boost && World::getWorld() != NULL) // motion blur
|
||||
if (isRace && UserConfigParams::m_motionblur && World::getWorld() != NULL) // motion blur
|
||||
{
|
||||
renderMotionBlur(0, *in_fbo, *out_fbo);
|
||||
std::swap(in_fbo, out_fbo);
|
||||
|
@ -2663,6 +2663,8 @@ namespace FullScreenShader
|
||||
GLuint MotionBlurShader::uniform_boost_amount;
|
||||
GLuint MotionBlurShader::uniform_center;
|
||||
GLuint MotionBlurShader::uniform_color_buffer;
|
||||
GLuint MotionBlurShader::uniform_dtex;
|
||||
GLuint MotionBlurShader::uniform_previous_viewproj;
|
||||
GLuint MotionBlurShader::uniform_direction;
|
||||
GLuint MotionBlurShader::uniform_mask_radius;
|
||||
GLuint MotionBlurShader::uniform_max_tex_height;
|
||||
@ -2672,6 +2674,7 @@ namespace FullScreenShader
|
||||
{
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/motion_blur.frag").c_str());
|
||||
uniform_boost_amount = glGetUniformLocation(Program, "boost_amount");
|
||||
uniform_center = glGetUniformLocation(Program, "center");
|
||||
@ -2679,17 +2682,21 @@ namespace FullScreenShader
|
||||
uniform_direction = glGetUniformLocation(Program, "direction");
|
||||
uniform_mask_radius = glGetUniformLocation(Program, "mask_radius");
|
||||
uniform_max_tex_height = glGetUniformLocation(Program, "max_tex_height");
|
||||
uniform_dtex = glGetUniformLocation(Program, "dtex");
|
||||
uniform_previous_viewproj = glGetUniformLocation(Program, "previous_viewproj");
|
||||
vao = createFullScreenVAO(Program);
|
||||
}
|
||||
|
||||
void MotionBlurShader::setUniforms(float boost_amount, const core::vector2df ¢er, const core::vector2df &direction, float mask_radius, float max_tex_height, unsigned TU_cb)
|
||||
void MotionBlurShader::setUniforms(float boost_amount, const core::matrix4 &previousVP, const core::vector2df ¢er, const core::vector2df &direction, float mask_radius, float max_tex_height, unsigned TU_cb, unsigned TU_dtex)
|
||||
{
|
||||
glUniformMatrix4fv(uniform_previous_viewproj, 1, GL_FALSE, previousVP.pointer());
|
||||
glUniform1f(uniform_boost_amount, boost_amount);
|
||||
glUniform2f(uniform_center, center.X, center.Y);
|
||||
glUniform2f(uniform_direction, direction.X, direction.Y);
|
||||
glUniform1f(uniform_mask_radius, mask_radius);
|
||||
glUniform1f(uniform_max_tex_height, max_tex_height);
|
||||
glUniform1i(uniform_color_buffer, TU_cb);
|
||||
glUniform1i(uniform_dtex, TU_dtex);
|
||||
}
|
||||
|
||||
GLuint GodFadeShader::Program;
|
||||
|
@ -759,11 +759,11 @@ class MotionBlurShader
|
||||
{
|
||||
public:
|
||||
static GLuint Program;
|
||||
static GLuint uniform_boost_amount, uniform_color_buffer, uniform_center, uniform_direction, uniform_mask_radius, uniform_max_tex_height;
|
||||
static GLuint uniform_boost_amount, uniform_color_buffer, uniform_dtex, uniform_previous_viewproj, uniform_center, uniform_direction, uniform_mask_radius, uniform_max_tex_height;
|
||||
static GLuint vao;
|
||||
|
||||
static void init();
|
||||
static void setUniforms(float boost_amount, const core::vector2df ¢er, const core::vector2df &direction, float mask_radius, float max_tex_height, unsigned TU_cb);
|
||||
static void setUniforms(float boost_amount, const core::matrix4 &previousVP, const core::vector2df ¢er, const core::vector2df &direction, float mask_radius, float max_tex_height, unsigned TU_cb, unsigned TU_dtex);
|
||||
};
|
||||
|
||||
class GodFadeShader
|
||||
|
Loading…
Reference in New Issue
Block a user