Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Per-object selective desaturation

Discussion in 'Editor & General Support' started by maxxa05, Mar 12, 2013.

  1. maxxa05

    maxxa05

    Joined:
    Nov 17, 2012
    Posts:
    186
    In a scene, I would like to desaturate all my scene except certain objects to put emphasis on them. I thought I could just put another camera in my scene that would only render the specific objects with a different layer, then select "Depth Only" Clear Flag and higher depth than my main camera, so this cam would render the objects in color on top of the other cam. But now those objects appear on top of everything else (see image).

    Is there any other way to do this? I thought of several solutions:

    1. I could put another desaturated camera with the few objects that would need to render on top. It would overcomplicate things and would add too much processing in my mobile app.

    2. Try to do something useful with the "Don't Clear" Clear Flag, which seems impossible

    3. I thought I could make a surface shader to put on objects in front of the colored objects. That shader would need to render pixels that would be cleared with the "Depth Only" Clear Flag, but I'm not sure it's even possible. In the situation of my image, I could just put the shader on a plane to mimick the desk in front.

    4. Replacement shaders or another solution that I don't understand :(

    Anyone could give input on this? Any tip or related link would be appreciated!

    $desaturation.png
     
  2. maxxa05

    maxxa05

    Joined:
    Nov 17, 2012
    Posts:
    186
    I found a way to mask objects with DepthMask on the unify community, but it's more of a temporary solution than something else because I've got to duplicate all the objects that could potentially be in front of my saturated objects.

    I'd still like to know if someone has a better idea, thanks!
     
  3. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Yes, that's exactly what you should expect, if you clear the depth buffer but not the color buffer.

    It shouldn't seem that way, as it's a viable solution.
     
    Last edited: Mar 12, 2013
  4. maxxa05

    maxxa05

    Joined:
    Nov 17, 2012
    Posts:
    186
    You were right, I just had to cull the saturated objects from the desaturated cam for it to work properly.

    Now my problem is that, on Android, it seems like effects are put on top of all cameras, so if I put an effect on the first rendered camera, it will render both camera, then calculate the effect on the first camera and the result will overwrite both cams, so the render of the second cam will disappear. It happens only on Android (tested on a Nexus 10, it's working on an iPad 3) with Don't Clear (working with Depth Only). Anybody knows whether it's a bug or a hardware buffer limitation?

    it seems I'm not the only one who got that issue:
    http://forum.unity3d.com/threads/172409-Don-t-Clear-Camera-Flag-breaks-Nexus-4
    http://answers.unity3d.com/questions/319430/camera-dont-clear-flag-doesnt-work-on-android-.html
     
  5. maxxa05

    maxxa05

    Joined:
    Nov 17, 2012
    Posts:
    186
    It seems to be problematic on pc too, the results are not predictable. If I put any image effect on the camera that is rendered first, there are all sorts of bugs, from the results of the first camera not appearing at all to the results of the first image appearing on top of everything else. As you could think, the difference in results seems to be related to the range of the cameras clipping planes. I keep both cameras with the same clipping planes.

    It seems to be the way unity manage image effects. As soon as you use Graphics.Blit, the problems mentionned above happen. Anybody knows a workaround for that?
     
  6. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Not for the general case. But if you're not doing any other render texture effects, you could just store the materials that need to be desaturated in an enumerable collection and then switch back and forth from the normal to desaturated versions with Material.keywords, in a loop. More of a pain, but it would probably save battery.
     
  7. maxxa05

    maxxa05

    Joined:
    Nov 17, 2012
    Posts:
    186
    I found another way to achieve what I wanted with replacement shaders. I created a monochrome and color version of each different shaders used in my project in my replacement shader, and I get the right shader version with a tag I created. It seems to be very lightweight, I even save 1 drawcall when I use the replacement shader!

    Your solution seems more robust than mine though, I may try it. Thanks for the help!