Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Colored path in grayscale world

Discussion in 'General Graphics' started by da_wasd, Nov 22, 2015.

  1. da_wasd

    da_wasd

    Joined:
    Jan 23, 2015
    Posts:
    6
    Hello!

    I'm trying to figure out how could I create a path that is colored and all rest of the world around the path should be grayscale. Kinda like masking part of the world along the path to bring out the color, to give the player visual cue where to go.

    What makes it a bit more complicated is that I would still like to have some of the objects such as players, projectiles, explosions and other effects, fully colored outside the path, so only the level geometry should be grayscale outside the path. The transition from color to grayscale should also be smooth.

    The path will be generated dynamically on the fly, so it's not an option to bake it in to textures etc. and it is 3D game, so the camera angle plays a role.

    I was thinking if something like this could be achieved by using shaders and particles (maybe post process fx?), but because I'm fairly new to the whole shared and postprocess stuff, I'm not sure how to approach this.

    Thanks in advance and if it helps I can try to illustrate this better with some shopped images.
     
  2. shanekim28

    shanekim28

    Joined:
    May 10, 2015
    Posts:
    7
    You could make another object e.g. a small plane, then make a script that duplicates the plane for every x amount of steps taken by the player (*cough cough* FOR LOOPS *cough cough*), and instantiate that small plane with the path material on it, and as the player moves away from the older paths, you could destroy the past ones. Try using Math.random() to set rotation. it could look something like this, but without the code, except, you know, closer together and better rotated and all that jazz. :D

    upload_2015-11-21_17-29-11.png
     
  3. TheAlmightyPixel

    TheAlmightyPixel

    Joined:
    Jun 21, 2014
    Posts:
    263
    You could use two cameras; one to render the objects that will be grayscale, and one to render the objects that will keep their colours.

    By adding a color-correction (I think that's what it was, I don't have Unity open at the moment so I don't really remember) post-process script on the grayscale camera, you can adjust the saturation of the rendered items to make them dynamically grayscale.
     
  4. da_wasd

    da_wasd

    Joined:
    Jan 23, 2015
    Posts:
    6
    Thanks for the ideas.

    Sonic, that was actually something I was thinking with the particle system approach. Or even use some spline tool to create mesh on the fly, to minimize vertices. Then slam some shader that is always "on top", so all the ground beneath it is colored. But my shader knowledge is not too good at this point and the objects/fx that should be colored makes it more complex.

    TheAlmightyPixel, if I use two cameras, wouldn't it mean that the last camera rendered will always be dominant, thus in a 3D game the colored objects can't never be behind the stuff rendered in the grayscale camera (in this case, the world geometry)? I also don't want to use extra cameras in case there are other ways to implement things, such as shaders as it is much faster performance-wice AFAIK.
     
  5. smd863

    smd863

    Joined:
    Jan 26, 2014
    Posts:
    292
    Find the smallest square that will entirely encompass the area you want your path to fit in (i.e. bounding box). Create a single-channel (i.e. Alpha8 texture format) 2D texture, and imagine it as a grid that will overlay this area. Depending on how big an area you want to cover, you can use more or less resolution for the texture. You can get bilinear filtering for "free" with the texture so you will get smooth interpolation, and it should look okay even if you are using a relatively small texture over a large area.

    Draw the outline of your path into the texture; preferably using SetPixels32 to set them all at the same time. In the vertex shader of your environment material, you will calculate the texture coordinates using the vertex world position and the scale/position of the bounding box for your path. In the fragment shader, find the luminance value of the final output color, sample from the path texture and use that as the alpha value to lerp between the final color and the luminance value.

    Set the texture to clamp, and make sure the border pixels of your texture are 0 so the area outside of your path bounding box will be entirely gray.

    That would be the fastest way to do it; all you need is an extra texture fetch, a dot product (for the luminance value), and a lerp for your environment shader. All of those are cheap. The most expensive part will be updating the contents of the path texture, but that should happen very rarely and even with a large texture would only cause a minor slowdown for a fraction of a second as the texture is transferred. Asynchronous texture upload is coming in Unity 5.3 so even that will disappear soon.
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,248
    Why not just use a custom shader on the environment that can be desaturated via a shader parameter (which you can control using a Shader.SetGlobal). If your lighting isn't significantly colorful this should "just work".

    Another option is to use a stencil mask or even the main render target's alpha to encode what you want to be desaturated and what to ignore. Again this would require a custom material on the environment, or on the characters and the path. As for effects the alpha method could handle that as long as you had a different material for effects you do what to be desaturated and those you don't.
     
  7. da_wasd

    da_wasd

    Joined:
    Jan 23, 2015
    Posts:
    6
    If I understand you correctly I think this might not work in my case, as the path can be spread in really large area. Tho, only small portion of it is visible at a time so it might work if I move the plane / redraw it once in a while from scratch etc. I will consider this as well.

    Thanks for the idea. Actually just heard about global shaders yesterday and I'm about to experiement with those today!

    The biggest problem I have right now (obviously), is that I have no deep experience with shaders and I really don't know how to mix them to get the result I have in my head (I know you can do almost anything with shaders). This is something I need to figure out by my self and I mostly want to get some general direction where to go.

    Any new ideas are welcome, but if I manage to do something cool, I will write about it here for sure.