Jump to content
  • Advertisement
Sign in to follow this  

Need some help w/ motion blur junk

This topic is 3329 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I was going through my big pile o' graphics papers again today, and rediscovered this underappreciated gem. I got to thinking, (and although they don't explicitly mention this usage) it turns out you can use the same trick for the post-processing variant pretty easily. Or so I thought. Seeing as my personal framework is currently down for the count, I did my best to hack together an implementation in the DirectX SDK. It worked, sorta. The quality of the blur is *great* at 16x-level aniso, and it performs slightly faster too (around ~550-600FPS using new method, ~480-500FPS using naive sampling) The downside is that for some unexplained reason, the tex2Dgrad appears to selectively reinterpret the derivatives as (AFAIK) {1.0, -1.0} with no apparent rhyme or reason. I've goofed with the math w/ no useful results, same problem. I remember reading somewhere that if the derivatives grow too high, it screws over the filtering. I distantly suspect this is the problem, though I can't imagine why values in the range [-1...1] would screw it up so. Here's a pitcher. Note the slick blurring. Does anyone have any ideas? EDIT: I just realized how enormously useless this is without code. Here. Have lots.
// Name: PostProcessMotionBlurPS 
// Type: Pixel shader                                      
// Desc: Uses the pixel's velocity to sum up and average pixel in that direction
//       to create a blur effect based on the velocity in a fullscreen
//       post process pass.
float4 PostProcessMotionBlurPS( float2 OriginalUV : TEXCOORD0 ) : COLOR
    float2 pixelVelocity;
    // Get this pixel's current velocity and this pixel's last frame velocity
    // The velocity is stored in .r & .g channels
    float4 curFramePixelVelocity = tex2D(CurFramePixelVelSampler, OriginalUV);
    float4 lastFramePixelVelocity = tex2D(LastFramePixelVelSampler, OriginalUV);

    // If this pixel's current velocity is zero, then use its last frame velocity
    // otherwise use its current velocity.  We don't want to add them because then 
    // you would get double the current velocity in the center.  
    // If you just use the current velocity, then it won't blur where the object 
    // was last frame because the current velocity at that point would be 0.  Instead 
    // you could do a filter to find if any neighbors are non-zero, but that requires a lot 
    // of texture lookups which are limited and also may not work if the object moved too 
    // far, but could be done multi-pass.
    float curVelocitySqMag = curFramePixelVelocity.r * curFramePixelVelocity.r +
                             curFramePixelVelocity.g * curFramePixelVelocity.g;
    float lastVelocitySqMag = lastFramePixelVelocity.r * lastFramePixelVelocity.r +
                              lastFramePixelVelocity.g * lastFramePixelVelocity.g;
    if( lastVelocitySqMag > curVelocitySqMag )
        pixelVelocity.x =  lastFramePixelVelocity.r * PixelBlurConst;   
        pixelVelocity.y = -lastFramePixelVelocity.g * PixelBlurConst;
        pixelVelocity.x =  curFramePixelVelocity.r * PixelBlurConst;   
        pixelVelocity.y = -curFramePixelVelocity.g * PixelBlurConst;    

    // META-COMMENT: The old code
    // For each sample, sum up each sample's color in "Blurred" and then divide
    // to average the color after all the samples are added.
    float3 Blurred = 0;    
    for(float i = 0; i < NumberOfPostProcessSamples; i++)
        // Sample texture in a new spot based on pixelVelocity vector 
        // and average it with the other samples        
        float2 lookup = pixelVelocity * i / NumberOfPostProcessSamples + OriginalUV;
        // Lookup the color at this new spot
        float4 Current = tex2D(RenderTargetSampler, lookup);
        // Add it with the other samples
        Blurred += Current.rgb;
    // Return the average color of all the samples
    return float4(Blurred / NumberOfPostProcessSamples, 1.0f);
    // META-COMMENT: My new stuff.
    float2 finalGrads = abs(pixelVelocity);
    float3 Blurred = tex2Dgrad(RenderTargetSampler, OriginalUV, finalGrads.x, finalGrads.y).xyz;
    return float4(Blurred, 1.0f);

Extra bits:
// Name: PostProcessMotionBlur
// Type: Technique                                     
// Desc: Renders a full screen quad and uses velocity information stored in 
//       the textures to blur image.
technique PostProcessMotionBlur
    pass P0
        PixelShader = compile ps_3_0 PostProcessMotionBlurPS();

and sampler junk:
sampler RenderTargetSampler = 
    Texture = <RenderTargetTexture>;
    MipFilter = LINEAR;
    MinFilter = ANISOTROPIC;  // was point
    MagFilter = ANISOTROPIC;
    MaxAnisotropy = 16;

    AddressU = Clamp;
    AddressV = Clamp;

[Edited by - InvalidPointer on June 8, 2009 8:27:56 PM]

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!