SebLague / Solar-System

Simple solar system experiment
https://www.youtube.com/watch?v=7axImc1sxa0
MIT License
1.15k stars 315 forks source link

How to use a layermask for the atmosphere and ocean shader/post processing? #51

Closed Panicat closed 2 years ago

Panicat commented 2 years ago

Not so much an issue but since this is the closest thing to a forum about this here I am again.

With the way the shader works right now even disabling a celestial body or making it invisible to a specific camera doesn't remove the ocean and atmosphere. Is there a simple way to implement a layermask for which atmospheres/oceans a post processing effect can render (which would be different per camera)? Thanks.

Delofon commented 2 years ago

Atmospheres and kceans are not game objects, hence you can't implement layer masks on them. However what you can do is interfering with PlanetEffects.cs' GetMaterials() method and its various checks. It's a scriptable object though, so for this to work differently for each camera you may need a new asset of it. Or you could just automate it somehow, but that's up to you.

Panicat commented 2 years ago

What would be a way of interfering with its checks like you suggested? I have pretty limited knowledge on this. Would there be a way to check for a tag on a GameObject that has the Celestial Body Generator, maybe when it gets the materials from the body settings? I don't know.

Panicat commented 2 years ago

Solved! In PlanetEffect.cs line 76, in the if statement you can put any check you want. If the if statement runs, then the atmosphere for the planet will be displayed. Let me show an example.

// Atmospheres
if (displayAtmospheres) {
    if (effectHolder.atmosphereEffect != null) {
        effectHolder.atmosphereEffect.UpdateSettings (effectHolder.generator);
        postProcessingMaterials.Add (effectHolder.atmosphereEffect.GetMaterial ());
    }
}

I believe that's what the original code looks like. Changing the if statement I can do a check for if the gameobject is on, because currently, disabling a gameobject still allows the atmosphere to show.

if (displayAtmospheres && effectHolder.generator.transform.parent.gameObject.activeSelf)

Now the global displayAtmospheres AND the planet object needs to be enabled for its atmosphere to renderer. I make the check be for the parent of the generator instead of the generator object itself (called Body in my case) because turning off the Planet (parent of Body) doesn't count as Body being set to inactive.

Obviously, here you could do any check you want. All you need to know is that the if statement runs for every generator in the scene - effectHolder.generator is the generator it is currently looping through. So you can do a layer or tag check on the planet and stuff like that!

Well I'm still not entirely sure how to do it differently per camera, but this works for me.