Skip to main content
GameDev.net gamedev.net
🔒 Locked

Motion Blur

Started by pcbrainbuster May 18, 2008 at 1:21 PM 7 replies 3.5k views
Original Post
pcbrainbuster
pcbrainbuster
Sup guys, How can someone achieve a classic motion blur effect? Also is there any good tutorial online? Thanks.
Harry Hunt
Harry Hunt
There's a demo in the DirectX SDK that does exactly that
Armadon
Armadon
Not a problem,
We have written a sample using MDX.
You could just rip out the shader and use it. But basically what you want to do is offset the texture a bit with an alpha component in directions.

Blur Sample

I hope this helps.
Take care.
Hodgman
Hodgman
Quote:
Original post by pcbrainbuster
How can someone achieve a classic motion blur effect?

Put simply: Blend the previous frame with the current frame.

The basic algorithm goes something like:

Allocate a texture the size of your screen (I'll call it ssLastFrame)

1) Render the world

2) If not the first frame: Render a 2D quad that covers the whole screen, textured with the screen-shot from last frame (i.e. ssLastFrame). Make sure alpha blending is turned on, and use a small alpha value, like 10% when drawing this quad. Tweaking the alpha value will change the 'strength' of the blur.

3) Take a screen-shot and store in ssLastFrame.

5) Render any overlays (or things that shouldn't be blurred), such as the HUD

6) Repeat
MJP
MJP
Quote:
Original post by pcbrainbuster
Sup guys,

How can someone achieve a classic motion blur effect? Also is there any good tutorial online?

Thanks.


What's the "classic" effect you're going for? There's quite a few different flavors you can choose from. There's the "motion trails" effect, which is what Hodgman is is talking about. There's the post-processing effect that's pretty popular these days, which is detailed in the PixelMotionBlur SDK sample. There's techniques that deform geometry based on the motion, such as the on in the DX10 sample. There's also the actual technically correct motion blur, which involves rendering multiple sub-frames and blending together for each frame actually displayed to the screen.

pcbrainbuster
pcbrainbuster
Thanks for all the replies guys.

The kind of blur I'm looking for would be the one Armadon just showed in his example but I do not work with managed DirectX :) Also the reason why I did not use the SDK is because its uses way to much extra code for an example which throws me off. So are there any online tutorials for it?

Thanks.
Evil Steve
Evil Steve
Quote:
Original post by MJP
There's the post-processing effect that's pretty popular these days, which is detailed in the PixelMotionBlur SDK sample.
Ooh, I never noticed that sample before - that looks pretty awesome.

Quote:
Original post by pcbrainbuster
The kind of blur I'm looking for would be the one Armadon just showed in his example but I do not work with managed DirectX :) Also the reason why I did not use the SDK is because its uses way to much extra code for an example which throws me off. So are there any online tutorials for it?
Armadon's one isn't motion blur, it's just plain blur (As far as I see).

The SDK samples are designed to be simple to follow - they all use the framework so you don't need to dig around to fing the relevant code, and if you look at the documentation in the SDK, it tells you exactly how the method works, even breaking down each function for you.
MJP
MJP
Quote:
Original post by Evil Steve
Ooh, I never noticed that sample before - that looks pretty awesome.


Yeah it's pretty neat to implement. Gives some decent results without too much overhead. However it can produces some really bad artifacts in some extreme cases. Plus it can be a pain integrating it with all your shaders, at least if you don't want to use a second pass to render out the velocity texture. There's also a neat variation of this technique where instead of rendering out a velocity texture you access a depth buffer to determine the screen-space location of the pixel in the previous frame. Then you use this velocity value to perform your blur, same as if you read it from a texture. It only works with movement from the camera unfortunately, but it's super-cheap if you have access to a depth buffer.

pcbrainbuster if you want to implement the technique seen in the PixelMotionBlur sample, the basic steps are this:

1. Render the scene as normal, but stored to a render-target texture.

2. Render the scene again, but this time to an R16G16F render-target texture. In this texture, you store the X and Y velocity of each pixel in screen-space. Basically you say "okay this pixel is here now, where was it in the previous frame? Then use that position to come up with a velocity. The shader looks something like this:

g_matWorldViewProj;     // Current World * View * Projg_matWorldViewProjLast; // The World * View * Proj used in the previous framevoid VertexShader( float4 in_vPositionOS : POSITION,                   float4 out_vPositionCS : POSITION,                   float4 out_vPosCurrentFrameCS : TEXCOORD0,                   float4 out_vPosLastFrameCS : TEXCOORD1 ){    out_vPositionCS = mul(in_vPositionOS, g_matWorldViewProj);    out_vPosCurrentFrameCS = out_vPositionCS;    out_vPosLastFrameCS = mul(in_vPositionOS, g_matWorldViewProjLast);}float4 PixelShader( float4 in_vPosCurrentFrameCS : TEXCOORD0,                    float4 in_vPosLastFrameCS : TEXCOORD1 ) : COLOR0{    float2 vVelocity = (in_vPosCurrentFrameCS.xy / in_vPosCurrentFrameCS.w) - (in_vPosLastFrameCS.xy / in_vPosLastFrameCS.w);    return float4(vVelocity, 1.0f, 1.0f);}


3. In a full-screen post-processing pass, blur the original render-target texture using the velocities stored in the second (R16G16F) texture.

float4 PixelShader( float2 vTexCoord : TEXCOORD0 ) : COLOR0{    // Sample the velocity texture    float2 vPixelVelocity = tex2D(velocitySampler, vTexCoord).xy;    vPixelVelocity.y = - vPixelVelocity.y;    // Move in the direction of the velocity, taking samples    // along the way.    float3 vSum = 0;        for(float i = 0; i < 12.0f; i++)    {           // Calculate the sample position        float2 vSamplePoint = vPixelVelocity * (i  / 12.0f) + vTexCoord;                        // Sample the scene texture        float4 vCurrentSample = tex2D(sceneSampler, vSamplePoint );                // Add it with the other samples        vSum += vCurrentSample.rgb;    }        // Return the average color of all the samples    return float4((vSum / 12.0f), 1.0f);}


[Edited by - MJP on May 20, 2008 1:33:25 PM]
pcbrainbuster
pcbrainbuster
I'm still working with the basics sadly and that looks like it is at a moderate level :( I think I'm in over my head with this motion blur thing... I guess I'll have to wait until I'm more experienced.

Thanks a lot guys.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.