Sign in to follow this  

Need some help w/ motion blur junk

This topic is 3112 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;
    }
    else
    {
        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 = 
sampler_state
{
    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

This topic is 3112 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this