Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[unity] Bug in pixel-lit shader - parts shining through #1335

Closed
HaraldCsaszar opened this issue Apr 22, 2019 · 3 comments
Closed

[unity] Bug in pixel-lit shader - parts shining through #1335

HaraldCsaszar opened this issue Apr 22, 2019 · 3 comments
Assignees
Labels

Comments

@HaraldCsaszar
Copy link
Collaborator

HaraldCsaszar commented Apr 22, 2019

As reported on the forum:
http://esotericsoftware.com/forum/Lit-shader-problem-with-layers-11810

Repro package received via email:
FMfcgxwCgLmmGMJhLtFczndPRWbfnZDx

Occurs in pixel-lit Spine shader variants with at least one point light.
It seems as if the add-pass does not properly do a depth-test but add the light in occluded parts of a character as well. This leads to an undiscovered shine-through effect.

@HaraldCsaszar HaraldCsaszar self-assigned this Apr 22, 2019
@HaraldCsaszar
Copy link
Collaborator Author

Potentially similar problem reported here on the forum:
http://esotericsoftware.com/forum/Simple-surface-shader-lighting-in-Unity-12307

@HaraldCsaszar
Copy link
Collaborator Author

HaraldCsaszar commented Jul 23, 2019

The problem has the following cause:

Background:
As can also be found on the ForwardRendering reference page:
Unity's forward renderer of the standard pipeline uses two separate passes:

  1. ForwardBase with Tags { "LightMode" = "ForwardBase " }
  2. ForwardAdd with Tags { "LightMode" = "ForwardAdd" }

The ForwardBase pass applies:

  1. a single directional light per pixel (even a single point light ends up in the add pass unfortunately),
  2. and all vertex lights.

The ForwardAdd passes (after the base pass) apply:

  1. a single per-pixel light via additive blending, on top of the existing base.

The problem:
Now if depth-write (zwrite) is disabled on both passes, the add pass will add light to hidden occluded regions.

Why?
Imagine the following scenario: Two parts overlap in view-order, zwrite disabled:

  1. The ForwardBase pass writes lit colored pixels of the base-lights for both the further-away and closer part to the screen correctly, but does not write depth to the zbuffer. Until now the color buffer of the screen is correct.
  2. Now the ForwardAdd pass will perform the depth-test (ztest) on the further-away part - it will pass since no zwrite happened in the ForwardBase pass before - thus it applies light to the hidden area and adds the resulting lit color to the screen buffer via additive blending. This part is incorrect and leads to the hidden part "shining through".
  3. The ForwardAdd pass then correctly computes the lit color of the closer part and additively blends it onto the screen. This addition is correct as such.

Solution:

  1. ZWrite has to be enabled and additionally:
  2. There has to be at least some minimal Z-Spacing between parts so that the depth-write really has any blocking effect of overlapping geometry. Z Spacing can be set in every SkeletonRenderer like e.g. SkeletonAnimation inspector, under Advanced - Z Spacing.

Also note that if Z Spacing does not move overlapping parts in Z direction, you will need to visit the Spine Editor to adapt the skeleton and re-export so that the overlapping parts can be on different Z-depth.

Alternative shaders:
Spine/Sprite/Vertex Lit shader
Note that you can also switch to the Spine/Sprite/Vertex Lit shader which uses the single-pass legacy "Vertex" tag. It works correctly due to the single pass rendering and can apply per-pixel lights.
Note however, that the legacy renderer will not be available in more recent Unity versions.

Lightweight Render Pipeline/Spine/Sprite shader
You can also use the new LWRP shader, see the Spine Unity download page and this issue ticket: #1255.

Proposed changes to the Spine-Unity 3.8 runtime

  1. The Spine/Sprite/Pixel Lit shader shall have ZWrite always enabled on the ForwardBase pass.
  2. Additionally, when this shader is detected, minimal Z Spacing shall be either suggested via a Warning-Box or automatically setup if set to 0.0.

HaraldCsaszar added a commit that referenced this issue Jul 24, 2019
…hining through - changed ZWrite to always On, otherwise ForwardAdd pass will incorrectly show lit hidden parts. Added recommendation warning box in SkeletonRenderer inspector for Z Spacing on enabled ZWrite shaders. Closes #1335.
@HaraldCsaszar
Copy link
Collaborator Author

Fixed on 3.8-beta branch via above commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

1 participant