Shadow Fadeoff approaching far clip plane

Hi,

So, this is an issue that has peeved me for a good while now, I reckon now is as good a time as any to ask about it.

The problem is as follows:

My game world (KSP) is too large for a single camera to render accurately. I have very close foreground objects (ships and such) and very distant objects (terrain). A single camera can’t render the near objects without causing severe z fighting issues on the terrain (especially along shorelines), and to render terrain stably, I have to push the near clip so far it clips off the player’s ship.

So, the solution is to use two cameras (on this layer. There are more cameras, but these are the ones that draw shadows, so they’re the ones that matter). A Near camera starts off at a very close near plane and far clips at about 1km. Then a far camera picks up from there and draws the world from 1km to 80km (past which the terrain is replaced by the scaled layers, which are beyond the scope of the issue).

The problem I have is in the transition between the near and far cameras. They stack up nicely for geometry, but there is a noticeable artifact with shadows. You can see it plainly here:

That hard edge is where the far camera’s frustum begins. If you look closely, you’ll notice that the edge is caused by the near camera fading off shadows as they approach the far end of its frustum.

I’ve looked far and wide, and so far haven’t had much luck finding anything about this… Admittedly, a multi-camera rendering stack isn’t exactly common, and for most single-camera rendering setups, this is actually a feature, as shadows gradually fade from view as they get farther away.

I’ve tinkered with the shadow settings quite a bit too. In the KSC scene as seen above, the shadow distance is set to 5000m, well past the far clip of the near camera. The problem is that the shadows will fade both when approaching teh shadow distance, or when approaching the far clip plane, and there seems to be no way to adjust this behaviour.

Just for reference, I’m in Unity 5.2.4 now, but this has been here since U4.x and possibly even earlier. I have never not had this behaviour. It also seems to be consistent across platforms and rendering APIs too.

If anyone has useful knowledge to share about this, it will be hugely appreaciated!

As always, thanks in advance!!

Cheers

3 Likes

Same exact problem here, and it is very frustrating and wreaks graphic havoc with our two-camera setup. Any workaround or fix? Thanks in advance!

I reckon this could be worked around by writing custom shaders which implement a new shadow receiving pass, but it seems like an awful amount of reinventing the wheel for something which could be a simple tweak on the other side of things.

Unless there is a way we can do this tweak ourselves… Is there a way to change the default shadow receiver behaviour for all shaders?

Cheers

Added a schematic drawing for clarity. Current version is 5.2.4, and this is still the same (not that I expected a fix in any case).

I did however, find that the shader cgincludes are all open-source and modifiable, so it seems like it might be possible to fix this on our end. However, those files are a maze of nested include directives and legacy support code. I couldn’t for the life of me find where this fade against the far clip is implemented. (In our case, for fwd-rendered soft-shadowed shaders)

If anyone with more experience digging through those shader sources is able to offer some ideas at this point, it would be immensely appreciated.

Again, thanks in advance!

Cheers

We’re in deferred mode, but might take a stab at it later. Anyways, can’t really understand why this does not have any Unity attention. Seems like it would be a very quick fix for the graphics team? Just make the shadow fade optional per camera, problem solved!

I struggle with this frequently. In open world games or games with far view, the unity shadow system is entirely inadequate and ugly, frankly. Unity said to me that it’s part of their plans to take a stab at shadows at some point, but this is very vague.

Another consideration is the performance loss from redundant multiple camera renders. Ideally Unity would support something like reversed depth (which would also help Rust a lot too) Outerra: Maximizing Depth Buffer Range and Precision

This would probably fix up shadows, except shadows afaik don’t have the same precision available due to stencil or some such, and therefore needs a new technique regardless similar to what UE4 does. But I’m not too clear on what that would entail.

If Unity implemented this, it should fix up pretty much all the problems, and be just as fast with the vertex shader notes in the above link for optimisations.

Keeping a finger on this subject.

2 Likes

Thanks for that link. I’ve actually done a similar thing here a while back to z-sort ksp’s map icons. Those draw to a fixed-depth canvas, so implementing a custom depth curve (mine isn’t logarithmic, but it’s similar in intent) was quite simple.

After I had that working, I was wondering if this couldn’t be applied to terrain/scenery shaders to offset the verts along z in the vert program, so they’re spaced more optimally along the depth range. That article answers a lot of questions I was mulling over about that. Sliding verts along z in projection space does seem to work, but it does create new issues that have to be solved afterwards. It seems they’ve solved quite a few already.

Trouble is though, in our case this would be a pretty massive restructuring of the game’s rendering setup. It’s definitely not a small fix… And considering that on the flip side, our dual camera setup only suffers from this shadow artifact (and a few other more minor glitches), the amount of effort needed to pull off the shadow fix probably makes it the more attractive option right now.

I do dream of one day being able to do away with the dual-camera setup entirely.

Cheers

I had an idea about this… on the last unity version there was a fix for some shadowing artifacts (thanks for that one, btw, we really needed it). I still have the previous versions here… My plan is to run a folder diff between the shader include srcs on both, and see what was changed, if anything.

A bit of a shot in the dark, but it might give an insight as to how/where shadows are set up. Those sources are impossible to navigate without a much more intelligent IDE than notepad++…

BTW, if anyone has suggestions of a good IDE for shader code editing, please share. I know VS has some new features, but I’d love to be able to see the shader code in a proper (C#-like) development env. :slight_smile:

Cheers

I don’t know if this plugin is working with Sublime Editor, but sounds promising :slight_smile:

https://packagecontrol.io/packages/Unity3D%20Shader%20Highlighter%20and%20Snippets

Hi. So tell me, did you resolve the problem with the fading shadows in the far clipping plane? Or did you change your approach?
I am facing the same problem (with a 3 camera setup) and can’t seem to find any reliable solution within Unity…

I guess the only way to go would be to implement your own shadows… :smile: I can help in this if needed, as I’ve done my own shadow mapping before. (That, and such a solution could work out nicely when rendering cascades per-camera. :))

I have to bump this.

This workaround will need to get your hands dirty :wink: Add following script onto the camera:

void OnPreRender ()
{
originalScreenSpaceShadowShader = GraphicsSettings.GetCustomShader(UnityEngine.Rendering.BuiltinShaderType.ScreenSpaceShadows);
GraphicsSettings.SetCustomShader(UnityEngine.Rendering.BuiltinShaderType.ScreenSpaceShadows, myScreenSpaceShadowShader);
}

void OnPostRender()
{
GraphicsSettings.SetCustomShader(UnityEngine.Rendering.BuiltinShaderType.ScreenSpaceShadows, originalScreenSpaceShadowShader);
}

Regarding the screenspace shadow shader itself add this line :

shadow += GET_SHADOW_FADE(wpos, vpos.z);

Note that it needs some more work as well. For example; in deferred, the directional light attenuate by itself at shadow distance and in forward, at shadow distance, everything will go dark. So these changes are only the basic idea.

What should I do if I don’t have any “screen space shadow shader”?
I can barely make a diffuse shader if I follow a -good- tutorial.
Google didn’t turn up anything either :frowning:

the shader is Internal-PrePassCollectShadows.shaderBuilt in shaders

@Tesrym : If you need help getting @Jordi-Bonastre 's solution to work, I can help. :slight_smile: I’ve done simple mods for the built-in shaders before.

Speaking of which…

@Jordi-Bonastre Is there a place, like maybe, a “suggestion box” where you can put in suggestions? (I think Unity Feedback has it… but my situation’s a little different) I made a small modification of the procedural skybox a while ago that I wanted to share, and wouldn’t mind seeing it included with the default shaders. :slight_smile:

Hi Unity, make it a per camera check box! thaaaaaanks.

1 Like

Yes I would like some help @FuzzyQuills
Jordi lost me.
I got some shader error about needing another pass (???) and UnityEngine.Rendering.BuiltinShaderType.ScreenSpaceShadows does not exist (is this a 5.4 beta thing?)

Hmm… I’ll have to check that API thing against the docs. (Or Jordi could enlighten us! :p)
Whats the error actually say?

Also, try importing UnityEngine.Rendering into your script. If that doesn’t work either… what version are you actually using? pre-5.3 probably didn’t have that…

Hi guys, I wrote an article in the Kwnoledge base section: https://support.unity3d.com/hc/en-us/articles/208504286

Let me know which information will be useful to be added, please.

2 Likes