So I am using a shader to create a fog-like effect on unity. the problem is that shader and how we are using this fog are creating massive fps drops. in our tests we find in low end pcs that disabling the fog objects almost doubles the fps on those machines. below I post the images from the shader and how it is building and an example in the scene on how we are using it. Looking for help in how to get similar results but not destroy the fps in low-end hardware
.
1. The expensive part is the noise.
If you look at the shader in your Project then click Compile and show code, you can see the instruction count is very large, almost entirely from that noise.
The solution is pretty simple: bake the noise into a seamless texture and sample that texture. If you search for “seamless noise generator” online you should be able to find some little web utilities that do this for you. But you should double check it! Sometimes they lie about being seamless or are insufficiently seamless.
2. The other expensive part is the overdraw.
I can’t quite tell from the scene pic, but it looks like you may be overlaying several of these fog sprites on top of one another. That means every pixel will be visited multiple tiles with an expensive shader. You’d be better off it you scroll your noise by world position (use Position node and use that for UVs). This will mean you don’t need to overlap them so much.
You might also consider putting the “overlapping” effect in the shader itself so perhaps you sample your texture a couple times - scrolling them at different speeds - and so it looks like you have thicker fog, similar to the effect of overlapping the sprites but cheaper. Though again I may be mistaken about what’s going on in your scene so if this is inapplicable ignore this advice.
thank you. in case one you are suggesting for us to use a texture with noise instead of the simple noise function. this will be kind of tiring but it works.
in the second case, we are using multiple layers at different points in the scene. I don’t get it when you said to scroll the noise by world position, what you mean is change the transform. position of the sprite itself instead of using tile-offset?
Not quite. I should be clear that whether this works for you depends on your requirements for how things look. It might not work for what you’re going for. I can’t say without knowing more about the fog effect you want.
So, let me describe a hypothetical situation where this kind of solution is ideal and you could adapt it for your case if you think it’s applicable. Scenario: let’s say you wanted fog so that it looked like there are two layers scrolling in parallax over the full screen. One way of getting that effect is to use multiple layers of sprites in the scene and move the transforms. This is less efficient b/c where there’s overlap there’s expensive overdraw.
Another way would be do the scrolling the shader. The shader becomes a bit more expensive but by eliminating overdraw it becomes cheaper. We could sample the texture twice with two different offsets that are scrolled at different speeds: for example, uv + fogSpeed * time --vs-- uv + fogSpeed * time * .5f.
But then there’s a problem. If our goal is to reduce overlapping fog sprites into one sprite, how do we cover the whole screen? If we move the fog sprite, the fog will look like it’s moving. The answer is the Position Node in the Shader Graph. Your Tiling and Offset node uses the UVs of your MainTex implicitly. You could instead plug in the World Position instead of the UVs. Now it is possible to move the Sprite’s transform within the scene b/c what noise appears where is from the position instead of the 0…1 uv of the sprite’s rect.
Likewise, you could not move the sprite’s transform and instead place multiple non-overlapping but adjacent sprites and it should look the same as a full-screen sprite (so long as you wire the position to places where UVs are being used). This would allow you to have pockets where there’s no fog while the fog looks contiguous and unbroken b/c the noise is from the position.