Search Unity

Make everything black except one object

Discussion in 'General Graphics' started by OpticalOverride, May 27, 2022.

  1. OpticalOverride

    OpticalOverride

    Joined:
    Jan 13, 2013
    Posts:
    161
    I've been trying to get this effect for over a month, but I have to admit my graphics programming experience is limited.

    [GOAL]
    I simply want everything in the scene (including any unlit and transparent elements) to be completely black except for a selected renderer. Opaque objects in front of the object should be black and hide the selected renderer. Transparent elements in front of the selected renderer should effect the renderer and shade it a darker color. Lighting and shadows should still effect the selected renderer.

    I've tried so many things I won't go into all of them, but every method I try has various drawbacks. I'll mention my most successful attempt so far, although I'm not sure if I'm even on the correct path...

    [My half working version]
    I use Post Processing to turn the Brightness on the scene to -100 (flat black), and then using a mask (from this thread https://forum.unity.com/threads/applying-image-effects-to-specific-objects.473226/#post-3156198) I cut the Post Processing image to allow the object to be seen in full color and lighting. The problem is transparent objects in front of the object are also seen in full color, and particles are simply bugged and often don't (but sometimes?) show up.

    I'm wondering if using something like the Stencil buffer to draw only the visible pixels of the selected renderer is the right way to go? I'm not sure if that's the right approach or if transparency of objects in front of my selected renderer could be taken into account that way...

    Any help or redirection on how to get this effect would be greatly appreciated :)
     
    Last edited: May 28, 2022
  2. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    Set the camera's clear color to black. Create a special layer for the one object that you want to show. Have the camera only render that one layer. Put that object in the special layer. The whole screen will be black except that one object.
     
    adamgolden likes this.
  3. OpticalOverride

    OpticalOverride

    Joined:
    Jan 13, 2013
    Posts:
    161
    Thank you for the reply! How I wish it were that simple :( And actually in some variations of my attempts that was part of the solution. However, this technique alone will ignore any transparent objects (or opaque objects) in front of the selected renderer, plus any shadows from other objects that may be casting on the selected renderer.

    As stated in my goal
    Hence why after a decade of Unity work I've been stuck on this problem for many, many hours :confused:

    [EDIT]: also edited my initial question to hopefully be more clear, thank you! :)
     
    Last edited: May 28, 2022
  4. joshuacwilde

    joshuacwilde

    Joined:
    Feb 4, 2018
    Posts:
    731
    Since you have opaque materials figured out, I will only comment on transparent. You have 2 options.


    1. Use custom transparent shaders for every transparent renderer. Add a color property to the shades that tints the color output, then use Shader.SetGlobalColor() to set it to white when you don't want a tint, and black when you do.

    2. This is an easier solution, but I am not sure if it will work correctly with additive materials, (maybe with premultiplied alpha it will). Add a command buffer that happens right before transparent rendering. Set a new render target in that command buffer. After transparent rendering, blit your new render texture on top of the screen using a shader that tints it darker at the same time (just multiply by a dark color).

    There might be other options as well, but this is just what I thought of immediately.
     
    lukas_dinox likes this.
  5. OpticalOverride

    OpticalOverride

    Joined:
    Jan 13, 2013
    Posts:
    161
    Thanks joshua, these are great suggestions!

    Suggestion 1 I feel may be difficult for my needs as there are many different particle effects and transparent objects in the scene, with many different types of shaders... I had considered changing them all but this would be a last resort.

    Suggestion 2 is interesting to me. As I said my graphics programming is limited, the only thing I'm unfamiliar with are command buffers and just looked them up to learn more. I'm not going to get a chance to look into it this weekend but hopefully next week I'll get a chance to mess with this idea. Thank you!