Search Unity

Cutout shaders with motion vectors / blur

Discussion in 'Image Effects' started by goonter, Jul 21, 2017.

  1. goonter

    goonter

    Joined:
    Aug 31, 2015
    Posts:
    89
    I'm using Unity 5.6.0p2 with Post Processing stack v1 commit a49365fcdff3eaf8366378604d911c410f78fd0e (latest) from github and it seems that transparent pixels of cutout shaders block motion blur effects, even though they shouldn't since there is nothing there.

    As you can see in the attached screenshot, the player's arm is blocking the ground blur effect even though the pixels are transparent (using a cutout shader). This happens with the standard cutout shader as well as my custom one.

    This seems like a bug, but any help would be appreciated. Thanks in advance!
     

    Attached Files:

  2. goonter

    goonter

    Joined:
    Aug 31, 2015
    Posts:
    89
    @Tim-C or any other Unity guys, is this behavior expected? Hope you can help!
     
  3. customphase

    customphase

    Joined:
    Aug 19, 2012
    Posts:
    246
    AFAIK thats because rendering motion vectors is done with replacement shader in a different pass, where your cutout doesnt apply.
     
  4. goonter

    goonter

    Joined:
    Aug 31, 2015
    Posts:
    89
    If anyone has this issue, I fixed it by writing a custom implementation of MotionVectorData VertMotionVectors(MotionVertexInput v) into my shader where I modify the vertex positions of the arm vertices to be collapsed inside the stump. So those vertexes get moved for the motion vector pass and aren't creating motion data at their original positions anymore.

    This seems like a workaround though. If the calculations are done with a replacement shader, it seems like that replacement shader should support cutout.
     
  5. tombuben

    tombuben

    Joined:
    Apr 2, 2019
    Posts:
    4
    I've been writing custom replacement motion vector shaders, and it isn't really documented well :/

    I've managed to make a custom replacement motion vector shader that works with cutout shaders properly - it's basically a copy of the internal Unity one I've downloaded from the built-in shaders package, with UV's passed from the vertex to fragment shader and these two lines on top of the FragMotionVector.

    Code (CSharp):
    1. fixed4 texcol = tex2D( _MainTex, i.uv );
    2. clip( texcol.a*_Color.a - _Cutoff );
    This solution makes sure the motion vectors are actually present correctly where Unity draws the surface and are not visible where unity doesn't draw anything. Just this works great for my use (I'm interested only in the motion vector buffer data, not the scene itself), but you can probably make it "global" by setting it up as a replacement shader by using SetReplacementShader() (or just by modyfying the shader Unity distributes with the editor).

    The proper solution would be to have a different way of computing motion vectors for each of the built-in RenderTypes, but I've been struggling with for a while with making materials with RenderType set to Transparent to output my custom motion vectors (I want to treat them as cutouts as well, so that transparency below certain threshold also outputs motion vectors). From what I've tried, I haven't managed to run the
    "LightMode" = "MotionVectors"
    pass on any subshader that has transparency, and using a replacement shader with the properly set replacementTag, only the first MotionVectors LightMode gets used.

    For a simple scene, you can always just make a custom variant of the shader, but I was hoping for a way to modify how all motion vectors are rendered in the scene at once to be easier...
     
  6. timsoret

    timsoret

    Joined:
    Apr 9, 2015
    Posts:
    16
    Would you share this modified shader? I only create shaders using nodal systems like Amplify Shader Editor, I don't know how to pass UV from vertex to fragment by code. I'd really like to finally have correct motion vectors in my cutout shaders, as they currently destroy TAA & motion blur.
     
  7. tombuben

    tombuben

    Joined:
    Apr 2, 2019
    Posts:
    4
    I'm not sure the shader will be of much help, since I haven't tested the visuals at all. My main goal was getting the motion vectors themselves, not using it in the unity post processing stack (used it to create some computer vision datasets). The replacement shaders kind of work, but Unity doesn't really allow you to replace only the the LightMode=MotionVector pass without replacing the main lightmode passes which are rendered on screen, so modifying all the cutout shaders that are used in the game with a custom MotionVector render pass is probably the only way :/

    With basic shaders written in ShaderLab it's "just" adding the motion vector pass with all the variables it requires to the file. I'm not sure if this can be done with Amplify since I never used it, but I think it also allows you to set tags to different passes, so it should be possible to do it as well. Not sure at all if it can be done when using a surface shader, since those are different beasts altogether.

    This shader is the motion vector cutout modification together with includes of the Standard shader distributed with Unity. With some small tweaks should work well:

    https://gist.github.com/tombuben/bc08f1b07c63c8298e2aa70af3d6f14c
     
    Last edited: Mar 31, 2022
  8. Alterego-Games

    Alterego-Games

    Joined:
    Jul 13, 2015
    Posts:
    354
    Our issue is that adding a Motion vector pass to our cutout shaders, our performance is greatly impacted because suddenly every object in the game is forced into the motion vector pass (99% off objects is cutout).

    Anyone found a better sollution?