# Question 2D Colored Fog Shader with URP

Discussion in 'Shader Graph' started by KingKonXI, Feb 26, 2024.

1. ### KingKonXI

Joined:
Apr 9, 2019
Posts:
22

I am trying to get this tutorial to work:

http://blog.moondrop.no/2016/08/creating-colored-fog-in-a-2d-game-with-unity/

I managed to run this in a new project just fine, but in my main project where i want to use this,
i am using the URP. unfortunately the shader and materials do not work in URP.

It seems like i would need to adapt the scripts, but I cant figure out how.
any help would be much apprechated.

regards
KM

2. ### Lo-renzo

Joined:
Apr 8, 2018
Posts:
1,520
(1) practice doing some very basic 2D shaders tutorials that you find on YouTube.
It can be a while to start to "get" shaders. So you may not want to advance to (2) until you kind of sort of get it.

(2) Get the shader working for one SpriteRenderer first.

Some nodes that may help are the:
Position node
Remap node
Saturate node (or Clamp node)
Lerp node

On the Blackboard define
- float for Min Height
- float for Max Height
- float for Min Depth
- float for Max Depth

For each of these pairs of floats (x2 height & x2 depth), use the Remap node on different position input component.

Just Getting Depth Working
Your scene should be arranged so Z changes how close to the camera a sprite is. Y should be up and down.

Use a Split node to get just the y-component or z-component of the position.

What you want to accomplish in the shader is: "if the sprite's position.Z is between 5 and 10 then color it red if 5 or less and color it blue if 10 or greater."

This would be plugging in position.z as input into a Remap node and remapping in with Min Depth and Max Depth to zero to one range. Then use Saturate to constrain the value between zero and one.

Then you can take that output (a value between 0 and 1) and input it into a Lerp node's input, which can lerp between two colors (red and blue for example). Then you can multiply this color to your sprite's MainTex color and put that into the output.

The next step would be doing the same for height but since it's essentially the same so I won't describe it.

Move your sprite around in the scene to see if it's behaving as expected and your Min/Max values are OK on your material.

(3) A problem for multiple SpriteRenderers is dynamic batching which can fuse positions together, so don't apply your material to all the renderers in your scene yet. Cross that bridge when you get there.

Last edited: Feb 27, 2024
KingKonXI likes this.
3. ### KingKonXI

Joined:
Apr 9, 2019
Posts:
22
Hi Lo renzo,

I was trying out your suggestions but i have a few questions:
1. remap takes 2 values for "min max in" and "-out" each, connecting minDepth and maxDepth to the remap node had no effect, when using the x, y or a vector 2 node i was able to get a switch of color when changing the z axis, however the change was almost immediately at the x value (z= -500 to z= -511) of the "in min max" (due to scale of my scene the values are -500 and +1000)

2. i would like to have a wide spread aka several semi colored layers. my main layer is at z=0 and the front layers are each seperated at a decreasing -100 step (-100,-200 etc) and the rear layers are 100,200,300 etc. how can i spread out the transition (from "normal" to "transparent-black" to "solid-black" in front and from "normal" to "transparent-color" to "solid-color" in back) over a greater distance ? and how would i add transparencies instead of a second color?

3. I am currently using a texture in the graph, but actually want to use the sprite the object already has, would the texture then changed via a script?

i included my graph below.

4. ### Lo-renzo

Joined:
Apr 8, 2018
Posts:
1,520
1. Create a Vector2 node. Plug in MinDepth into x, and MaxDepth into Y. Then plug the Vector2 into the InMinMax input of the Remap Node.

For OutMinMax, put 0 and 1. Overall the remap is saying "convert the input value from position.z into an output value between zero and one, where MinDepth is zero and MaxDepth is one."

The Clamp node with 0 and 1 good, but it's output should go into Lerp's "T" input.

Lerp's A should be red, Lerp's B should be blue. Lerp is saying "for values near 0, output A; for values near 1, output B." T stands for "time" which is typically normalized between zero and one as you have already done.

The rest looks fine.

2. You could accomplish this with a Gradient and Sample Gradient node. This takes a 0..1 input and you can then define whatever color transitions you want over the gradient. You might need a second gradient and sample for the alpha. To make semitransparency, you want multiply the SampleTexture's alpha output by your modifier (from the gradient) and plug it into the Alpha output in the Fragment stage output far to the right.

3. For a SpriteRenderer, it expects you to have add a texture to your blackboard and name it MainTex (it needs that name exactly). Then it should automatically grab the correct sprite from the SpriteRenderer.

KingKonXI likes this.
5. ### KingKonXI

Joined:
Apr 9, 2019
Posts:
22
thanks, the color now changes smoothly and also the mainTex works as it should!
for 2, i basically want to controll the "tickness" of the fog, aka the opacity also depending on the z axis.

imo i need two gradients, one for the front from transparent to black --> z=0 to z=negative-clampvalue (where its 100% black) and one from transparent to color --> z=0 to z=positive-clampvalue (where its 100%color).

wouldnt i replace the color (red and blue) nodes with the actual gradient values? and can i bind the front 0 rear gradients into one node depending on the value?

this is the graph currently

File size:
157.7 KB
Views:
13
6. ### Lo-renzo

Joined:
Apr 8, 2018
Posts:
1,520
yes! that's exactly what you should do. The gradient can replace lerp & colors, with Time corresponding to Lerp's "T" input.
not so sure I understand what you mean fully, but probably. A good deal of shader work is just fiddling around until it looks right.

KingKonXI likes this.
7. ### KingKonXI

Joined:
Apr 9, 2019
Posts:
22
Thanks,
I am still playing around with this, and it works almost as intended, but i only want the alpha of the gradient to decrease (and the color(=fog) to increase) the sprite itself should be visible 100% in all stages. Wenn connecting to the sprites (fragment) alpha the sprites opacity decreases.

The end result should look like this;

in this, the 4. sprite is the "normal" with no gradient on z= 0. I was wondering if this needs two gradients, one to handle negative z (transparent to black) and one to handle positive z (transparent to color) or if this can be combined into one gradient with black and color?

this is the current state which is close.

File size:
143.4 KB
Views:
13
8. ### Lo-renzo

Joined:
Apr 8, 2018
Posts:
1,520
If I understand you correctly, it has a 'fixed' value in this case based on its position.z so that's just one value per sprite. That's because you're billboarding the sprites toward the camera; across the whole sprite it is has a single z-position. If you were to rotate your sprite so it's flat, laying down in the z-plane, then it'll have multiple values.

Since we normalized z-values to 0..1 you shouldn't need to think about positive and negative z. Instead, it should have all been remapped to 0..1. You can adjust your MinDepth and MaxDepth values to change how the range that's remapped.

A single gradient can support alpha. If you open up the gradient node, there are little markers which let you define color, but above those there are more little markers - these are for alpha.

So you should be able to define:

transparent
to opaque
to transparent

all within a single gradient with those upper markers.

You're currently not handling alpha at all in your graph. You should take a Split node, get the final color right before putting it into the Fragment output, then split off w and put that into the Alpha output.

KingKonXI likes this.
9. ### KingKonXI

Joined:
Apr 9, 2019
Posts:
22
ok some new progress:

i now have black in front, color, and black again.
its not completely what i want, but if the black in the back gets switched to the acutal color than its close.

Joined:
Apr 9, 2019
Posts:
22

11. ### Lo-renzo

Joined:
Apr 8, 2018
Posts:
1,520
You shouldn't need to do it like this. Check out my latest post above. A single gradient should work for you. Click on the gradient to open it up and define more color and alpha markers and it'll interpolate between the colors for you. I think each gradient can have quite a few markers for both alpha and color... like 8? It can interpolate between a lot of different colors.

Important concept: a gradient with a fixed time is just like using a Color node so it's not necessary.

KingKonXI likes this.
12. ### KingKonXI

Joined:
Apr 9, 2019
Posts:
22
understood with the single value, makes sense when its at a single z position.

i might not need to seperate alpha at all, if i just want to tint the sprite its handled via the gradient itself since the sprites transparency will not be touched

I minimized this to just one gradient, and i understand the gradients alpha values:

with just one gradient the scene is looking like this
and the graph like this

i do not see yet, how i can leave the front with the black fade like it is, but use the color fade for the rear, which is currently not visible.

13. ### Lo-renzo

Joined:
Apr 8, 2018
Posts:
1,520
You really should be able to get it to behave the way you want by connecting the Remap into a Clamp with (0, 1), then directly into Sample Gradient's Time and then outputting the that directly into the Multiply with the Sample Texture. The smoothstep, lerp and multiply nodes could be removed.

Then all you need to do is rearrange the markers on the Gradient. So long as your scene has its z-values within the Min/Max range of the your MinDepth/MaxDepth then it should be good to go. Don't forget to double check the Min/MaxDepth values on the material.

KingKonXI likes this.
14. ### KingKonXI

Joined:
Apr 9, 2019
Posts:
22
if i reduce the graph i still get the black and a fade to color but not to solid color and not to full transparent

mindepth is set to 0 (tried -1000)
maxdepth to 1 (tired +5000)

crate in front is at z = -1705
farthest crate is at z = +3029

15. ### Lo-renzo

Joined:
Apr 8, 2018
Posts:
1,520

You need to split the alpha and connect it to the Alpha output.

KingKonXI likes this.
16. ### KingKonXI

Joined:
Apr 9, 2019
Posts:
22
yes, this makes the sprite transparent,
but i only want the fog to be transparent, so that the underlying sprite is visible 100% with no color change
splitting the alpha off makes the sprite invisible

Joined:
Apr 9, 2019
Posts:
22

18. ### Lo-renzo

Joined:
Apr 8, 2018
Posts:
1,520
Oh I see.

Right now it's doing Tinting

Perhaps what you really instead want is Lerp instead to emulate the Fog.

So instead of the Multiply node, you'd put a Lerp node with ColorA being your MainTex color and ColorB being your Fog color (from Gradient). Then you get the Gradient's Alpha with a Split node (w) and plug that into the T value of the Lerp.

KingKonXI likes this.
19. ### KingKonXI

Joined:
Apr 9, 2019
Posts:
22
if i add a another color to the gradient i can see the difference.
somehow lighter colors have no effect on the rear tinting

the above is with a yellow marker

same image with yellow marker in blue:

View attachment 1377737

it seems like lighter color has no effect? maybe because the color of the crate is in the same color range and multiply has therefore a weaker effect?

i try your suggestion with lerp now and report back

20. ### KingKonXI

Joined:
Apr 9, 2019
Posts:
22
with second marker in blue:

21. ### KingKonXI

Joined:
Apr 9, 2019
Posts:
22
YEEEES

the lerp is working with the alpha split off

22. ### KingKonXI

Joined:
Apr 9, 2019
Posts:
22
thank you so much for your help,
can i tip you somehow?

23. ### Lo-renzo

Joined:
Apr 8, 2018
Posts:
1,520
No problem, glad to help! You can like my posts.

KingKonXI likes this.
24. ### KingKonXI

Joined:
Apr 9, 2019
Posts:
22
its me again. i have a follow up question.
the shader above works in a project where i use URP.
however i would like to add this shader to instances of a prefab which use an image component and the URP shader, and combine the effect of the shader above and the sprite-lit-default material.

can this be done or would i need to combine URP and the shader above into one shader graph?

currently only one has an effect, depending on which is set in the inspector

25. ### KingKonXI

Joined:
Apr 9, 2019
Posts:
22
nevermind, when i change the material of the image component, during runtime, it combines the lit-shades and the fog shader.
and the colored box i was seeing can be easily fixed by linking the alpha output of the texture to the alpha of the fragment so that it is preserved