1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
Dismiss Notice
Like RaceDepartment on Facebook.

Motion blur shader?

Discussion in 'Racer' started by Mr Whippy, Nov 9, 2011.

  1. The current one in the renderer/full screen shaders folder doesn't seem to work so well.

    I remember a Racer version just pre-CSM betas that had a really nice motion blur. If you had the camera on an external view watching the car from the side, the wheels would blur nicely, the track around you would blur, but the car was nice and solid.

    If the camera was fixed and panned as you drove the car past, your car was sharp and the track blurred.


    I've been looking through trying to find the code to make that old motion blur work but it doesn't seem to (I'm out of my depth massively here haha)


    It just seems a shame right now that we have no motion blur. Just watching Forza4 and GT5 videos again lots, along with GTA4, and it adds so much quality, simply through being present and also by hiding the lack of detail once you are moving.


    It would be great to get it blurring in the HDR space too, so on a night we get lines left behind our headlights for example :D


    Anyone with a bigger scripting brain have any ideas if this is possible or not. The current (bad) motion blur doesn't seem too costly really, it's just wrong hehe :D

    Dave
     
  2. Stereo

    Stereo
    Premium Member

    The blur currently in Racer seems ok, just needs a bit of tweaking (note that this car does have wheel blur models)
    [​IMG]
    from fixed outside cams the car doesn't have any blur.
    [​IMG]
    It's not easy to drive this thing straight which is why the car's kinda blurry too since the driver cam uses inertia...

    Turned off CSM and live envmapping to show blurred wheels on something without the models, it looks ok as long as framerate is high enough. (just starting a burnout so only back wheels are spinning and the car's not really moving)
    [​IMG]

    Specifically I have motion_blur.accum_factor=0.8, motion_blur.blur_alpha=0.7 set here.
     
  3. Hmmm, isn't accumulation factor not used for method 4? (racer.ini note seems to say so)

    Seems only the blur alpha works, and it only works nicely when FPS are high, which is never gonna happen any time soon :D

    Hmmm...

    It does look nice in those images though, maybe I've broken something messing in the shaders somewhere...!?


    Apart from the blur_alpha thing (which just blurs the frame buffer), did you set a 'blur' FS shader in the fs_filter1 slot in racer.ini?


    Perhaps the one I'm thinking back to that worked nicely was in pre-csm days, and thus ran the OGL accumulation buffers and higher FPS... seemed visually nicer anyway.

    I'll post an old video I made at the time, looks really good!


    Dave
     
  4. Stereo

    Stereo
    Premium Member

    I am using bloom_shadows_f.cg in that slot, I think it's probably mostly just a matter of FPS - I get 500+ in nocg which should definitely make it look smooth.

    Didn't notice accum_factor was method 1 only, I suppose it is just the one factor.

    The velocity map should have worked for a smooth blur independent of framerate, but wasn't rendering correctly. With an accurate x/y velocity shader, everything except wheels would look good, and I think those would just need a little shader tweaking to be tolerable.

    I think the best option for nice looking blur would be to combine the two - a velocity map blur gets rid of pixel-level details better, while the blur_alpha - being a more accurate representation of large-scale movements, since it actually simulates them - catches some details the velocity map can't. The trick would be combining the two in a smooth fashion.

    [​IMG]
    Large dots represent each rendered frame - the ones that can be used by the accumulation blur. Small dots represent the velocity map blur, which was briefly working. The black line in the upper image shows the trail of where the object was as it moved from red to green - a perfect motion blur would be sampling exactly along that line. By combining the two, you get the green dots, which don't follow the path perfectly, but do a lot better than either method on its own.

    To refine the velocity map further, it wouldn't just be casting out in straight lines - it would read in the velocity map at each position, and use that for the next step-forward. This way at the edges of stationary objects it would hit that and stop.

    Bottom plot shows approximately how each step combines to get the total output pixel. I believe the curves used are called cubic interpolation splines, basically translating the velocity map to a distance moved per frame lets you select these. The total's not quite a smooth ramp, but it's pretty decent. In order to improve that, the velocity map's splines would depend on the framebuffer's blur_alpha value, to change the slope of the line at each point. This would actually weight the blur slightly forward in time, to compensate for the framebuffer's bias backwards in time.

    I guess another concern is calculation time for the blurs.

    The framebuffer one is very light - multiply the old pixel value by blur_alpha, the current pixel by 1-blur_alpha, and add the two.
    The velocity map does a series of texture lookups proportional to the number of points - so if as in the drawing it's doing a 7 point spread, 6 lookups and additions per pixel. So it does reduce the framerate a little more, but then again, it's performing a blur the framebuffer could only get with 4 times the overall framerate.



    To make the motion blur accurate (rather than just looking nice) we'd need to consider the exposure time of whatever's doing the filming. Racer.ini says blur_alpha is set for a framerate of 100 fps, which means that with it set to 0.5, that's 0.5 of the current frame, 0.25 of the previous, 0.125 of the previous, etc. as drawn in my picture (the big dots), with each step being 0.01 seconds, so the curve covers approximately 0.05 seconds exposure, though not uniformly - it's mostly at the present time. If you wanted to simulate a night-time camera that exposes for about a second, you could set blur_alpha = 0.955. At this point you get a rounding problem, though - low pixel values (under 23) round up instead of down, so on parts of the screen darker than that, the old image never completely fades.
     
    • Like Like x 1
  5. Hmmm, I think I get most of that :D

    I wonder what games like Forza and GT5 use, since their shading in this regard is clearly relatively light, and yet looks really good. Iirc, they run about 60fps in their game engine? The alpha blur doesn't look as sweet as FPS drop under 100 to my eyes.

    More testing is needed for me, but currently it seems only blur alpha between frames is used as a motion blur simulation.

    It would be nice to get the velocity map method working again :D Or some other good method.

    I remember posting on here (iirc) when we got the really good motion blur just pre-CSM, and noting it would mean the end of wheel blur models! But we are back in the place of needing to make them again :D

    Dave
     
  6. Most games just use a special screen-space shader with velocity map. They somehow exclude the player car from the shader, so it doesn't get blurred.
    There is no way I know of to get good radial blur on wheels other than using mutliple models/textures and some shaders.

    Interestingly, I don't remember anything like that. There was the accumulation buffer method that almost worked for wheels as well, but it was very slow.

    Once again, I don't think there is a solution out there that would provide a true motion blur effect along with blurred wheels.

    I for one, would be happy to get the method rFactor uses for blurred wheels - the wheel material has texture animation that switches to the next texture as the wheel is spinning faster. When combined with a little blending between the textures (rF does not do that) we could get pretty convincing results.

    Driver: San Francisco has a similar method for wheel blur afaik.
     
  7. Stereo

    Stereo
    Premium Member

    I really should go to bed, but I fooled around a bit with the velocity map blur. Since it's not rendering the car properly (seems to skip it entirely for the velocity map pass???) I imitated a radial motion by spinning the camera.
    [​IMG]
    Top: default with Racer
    Bottom: tweaked to not be so bad.

    Would be nice if the car wasn't all blurry with the velocity map.

    Enabling both at once is hardly affecting my FPS, there's just the one issue that it's not including the car in the render, so it blurs the same as whatever track objects are behind it...
     
  8. [​IMG] [​IMG]
    [​IMG]

    I've tweaked motion_blur.cg and got these results . Seems like it was exagerated a lot , now it's fine !
     
    • Like Like x 1
  9. Please post the shader! kthxbye :)
     
  10. Here it go !

    motion_blur.cg
    Code:
    //
    // Combine scene FBO+velocity map to get motion blurred end result
    // Needs renderer.motion_blur.method at 4 and fs_filter1=<this_file>
    // RvG, 25-2-09
    //
    
    float2 MB_GetVelocity(sampler2D velocityMap,float2 tc0,float texWidth,float texHeight)
    // Get a velocity sample.
    // Decodes the 8-bit encoding to get a real screen velocity.
    {
      float4 velMap=tex2D(velocityMap,tc0);
      float2 vel;
      
      // Get X velocity. Red contains positive velocity upto 255 (=1.0 in shader terms)
      // Add negative velocity as well (either R or G will be non-zero)
      vel.x=(velMap.r/texWidth-velMap.g*1/texWidth);
    
      // Vertical (Y) velocity (positive)
      vel.y=(velMap.b/texHeight-velMap.a*1/texHeight);
    
      return vel;
    }
    
    float4 MotionBlur(sampler2D sceneMap,sampler2D velocityMap,float2 tc0,float texWidth,float texHeight)
    {
      //float4 baseColor=tex2D(sceneMap,tc0); 
      float2 vel;
    
      // Get raw velocity
      vel=MB_GetVelocity(velocityMap,tc0,texWidth,texHeight);
    
      // Scale down filtering to avoid overdoing blur
      const float maxVel=0.1f;
      float l;
      l=length(vel);
      if(l>maxVel)
        vel*=maxVel/l;
    
    //color.r=length(vel);
    //color.gb=0;
    //return float4(color,1);
    
      float3 color;
      // Enough motion to filter?
      if(abs(vel.x)<1.0/texWidth&&abs(vel.y)<1.0/texHeight)
      {
        color=tex2D(sceneMap,tc0).rgb;
      } else
      {
        // Sample along line
        const int numSamples=32;
        int    i;
        float2 tc=tc0;
        vel/=float(numSamples);
        for(i=0;i<numSamples;i++)
        {
          // Keep texture coordinates within 0..1
          tc=saturate(tc+vel);
          color+=tex2D(sceneMap,tc).rgb;
        }
        color/=numSamples;
      }
    
      // End color (average)
      return float4(color,1);
    } 
    
    
    float4 MotionBlur2(sampler2D sceneMap,sampler2D velocityMap,float2 tc0,float texWidth,float texHeight)
    // Weighted to account for null-velocity samples
    // Used to counter the echo effect on cars near fast-moving objects (road for example)
    {
      float2 vel;
    
      float3 color;
      // Color when no blur is used
      float3 nonMBcolor;
      
      // Get unblurred sample
      nonMBcolor=tex2D(sceneMap,tc0).rgb;
        
      // Sample along line
      const int numSamples=32;
      const float oneOverSamples=1.0/float(numSamples);
      int    i;
      float2 tc=tc0;
      for(i=0;i<numSamples;i++)
      {
        vel=MB_GetVelocity(velocityMap,tc,texWidth,texHeight);
        if(abs(vel.x)+abs(vel.y)<0.0005f)
        {
          // Don't blur in this signal
          color=tex2D(sceneMap,tc0).rgb*(i+1);
          color+=nonMBcolor;
          // Reset color entirely
    //        color=nonMBcolor*(i+1);
        } else
        {
          color+=nonMBcolor;
          // Keep texture coordinates within 0..1
          tc=saturate(tc+vel*oneOverSamples);
        }
      }
      color/=numSamples;
    
      // End color (average)
      return float4(color,1);
    } 
    
    
     
    • Like Like x 1
  11. So do I just use that code instead of the current one, and then use a motion blur FS shader entry?

    Do I need to enable the velocity map?


    It looks really good anyway... your FPS are also really good, I wonder if it'll look so hot on my system (nearer 60fps than 120fps!)


    Thanks

    Dave
     
  12. I'd disabled env mapping and shadowmap because they are really costly =/ You need to enable velocity map and put on racer.ini these configurations at motion_blur blur_alpha=0.7 ; (Method 4 only) fs_filter1=bloom_shadows_blur_f.cg
     
  13. Ah ok, thanks for that!

    Yeah, envmapping is costly.

    I run it to update one side per frame, so change the setting of 6 (all cube sides), to 1 per frame (one cube side), which saves some FPS.


    It'd be nice to have a way to run a fixed envmap that gets updated when large scene changes happen, somehow. Not sure :D

    Dave
     
  14. How do i enable motion blur?
     
  15. This motion blur method only seems to work with FPS > 125 or so... Usually the FPS is lower, be it via vsync or because of high quality content etc.

    The only successful motion blur today is via fullscreen shaders and it only works for normal scenery. Blurred wheels still need to be done with separate models/textures.
     
  16. I would like to see more on this Stereo. Which shader are you using? The only velocity map shader I see looks terrible. If you're in a car the dash will blur like you're going into hyperspace.

    Alex Forbin
     
  17. Stereo

    Stereo
    Premium Member

    Same thing, it only renders the track so it's not much good unfortunately, since it sees the track behind the dashboard that blurs too.
     
    • Like Like x 1
  18. I wonder if we use the depth map to set a limit?

    Alex Forbin