- Uređeno
[Unity URP] Spine/Sprite shader artifacts in Chrome WebGL.
Hello. This problem may sound a bit far-fetched, but it's critical for my project. I'm a Spine Pro customer.
Environment: Windows PC, Nvidia GPU, Unity 2019.3.8f1, URP 7.3.1, Spine runtime and shaders 3.8, Chrome 81.
Conflicting asset: https://assetstore.unity.com/packages/vfx/shaders/fullscreen-camera-effects/massive-clouds-screen-space-volumetric-clouds-131898
I've spent quite a bit of time identifying the issue and it's probably related to Spine URP Sprite shader, because none of the other transparent shaders have this problem.
The scene is made of sample assets, using the stretchyman_Material with enabled "Write to Depth" (won't reproduce when it's disabled).
Firefox screenshot (looks alright):
Chrome screenshot (broken):
GIF of this bug in the actual project:
Seizure alert. https://i.imgur.com/XTqrful.gif
Steps to reproduce:
- Open ReproductionScene in the Assets folder.
- File->Build Settings->Build on a WebGL platform.
- Run Chrome browser with this argument to allow launching local build:
allow-file-access-from-files
- Type build path in the address bar, like D:/Work/Trash/URPSpriteBugRepro/Builds/WebGL/index.html and hit enter.
- Observe the corrupted pixels on sprite edges. They are extremely bright and cause the bloom effect to go wild.
Reproduces on Opera as well.
I can't share the download link publicly since it's using a paid asset, so I've sent @Harald a personal message with minimal reproduction link, including build and the project.
Things I've done so far:
Disabling texture compression.
Trying to clamp output of ForwardPassFragmentSprite in Spine-Sprite-ForwardPass-URP.hlsl like so:
if (pixel.r > 1 || pixel.g > 1 || pixel.b > 1)
pixel.rgba = half4(0, 1, 0, 1);
return pixel;
Didn't work. Bright pixels do get green color, but the artifact still persists. Artifact colors are random as well:
Thanks for sending the package, we received everything. We will get back to you as soon as we've figured out what went wrong.
It looks as if there is some kind of optimization going on in regards of (not) clearing the framebuffer completely to the skybox color that messes with the result: When you scale the skeleton smaller, so that the edge does not overlap with the skybox area but with the cube, the problem does not occur. When the framebuffer not being cleared in the problematic region, then the (premultiplied) additive blending of the Spine shaders adds to an ever-increasing value every frame. Note that setting the Spine shader to straight alpha
still uses additive blending, it performs the necessary PMA multiplication in the shader with the texture. Other shaders do not cause this problem since they are nort using additive PMA blending. At least this is my current best guess.
What I cannot reproduce though is the green area at the hand in your screenshot, however this could be a result of momentary bloom artifacts.
Harald wroteWhat I cannot reproduce though is the green area at the hand in your screenshot, however this could be a result of momentary bloom artifacts.
Thanks a lot for looking into that. Don't mind the green hand, it was a result of my clamping experiment where I set the output of a fragment shader to green whenever any pixel exceeds value of 1.
I'm not that great at shaders. You've made much more progress by just looking at it.
But uh, I still need the URP/Spine/Sprite shader because it has way more features that I'm actively using. Let me know if I need to poke the procedural sky developer (or maybe Chromium developers ?) to solve that problem.
Carl wroteYou've made much more progress by just looking at it.
I also modified multiple parts of the Spine shader for testing purposes, so I did more than just look at it.
Carl wroteBut uh, I still need the URP/Spine/Sprite shader because it has way more features that I'm actively using. Let me know if I need to poke the procedural sky developer (or maybe Chromium developers ?) to solve that problem.
While I'm not quite sure where exactly the problem comes from, I think a good workaround would be to not rely on the unity-skybox (the blue and brown sky without the clouds). I think the procedural clouds asset is ok, you could just draw it on top of e.g. a colored quad with the same blue color at the top, brown at the bottom, to have something that writes to the depth and color buffer reliably.
The problem could be the WebGL backend of Unity (or the Chrome specific part of it), or their bloom shader code. If the above workaround is not sufficient or is unclear (using something in front of the Unity skybox), please let us know.
- Uređeno
Harald wroteYou could just draw it on top of e.g. a colored quad with the same blue color at the top, brown at the bottom, to have something that writes to the depth and color buffer reliably.
Hey. I've spent an entire exhausting day, but it was impossible to get clouds to draw on top of anything that's drawing depth. I tried everything including overlay cameras, render objects, custom render features and draw order adjustment.
I decided to dig deeper into the root cause of this problem, figured it out and filed a bug report to Unity. Here's a copy of my report with reproduction project links. https://hatebin.com/hsvlfsfesk
Then I've made a workaround for Spine shader that solves this problem.
At the very bottom in Spine-Sprite-ForwardPass-URP.hlsl you can set the output alpha of a fragment shader to 1, like so:
pixel.a = 1;
return pixel;
Obviously that's a temporary solution that looks rough around the edges and breaks sprites that don't use depth.
I'm not that great at shaders, so I'd really like a proper solution that won't break things.
Here's a modified repro with the workaround above. (it's no longer using a paid clouds asset). https://drive.google.com/open?id=1IeQHyL1LfEFZpxsQ7fLxwRokUani8GMU
I kinda went through hell, want to take a break now.
Sorry to hear that. Thanks for sending Unity a bug report, I had a look at your new reproduction project, very minimal indeed.
Carl wroteObviously that's a temporary solution that looks rough on the edges and breaks sprites that don't use depth alpha cutoff.
I'm not that great at shaders, so I'd really like a proper solution that won't break things.
The problem I see here is that in order for a Spine shader to work properly, it seems that the blend mode must not be additive here. Unfortunately all Spine shaders use additive blend mode, so changing the code to work with Blend SrcAlpha OneMinusSrcAlpha
would require the shader code to not perform the multiplication with alpha when straight alpha
workflow is used. Unfortuantely modifying Spine shaders this way involves many modified or copied include files and modifying the SpineSpriteShaderGUI
Inspector code as well to display any additional new Sprite shader. So this is not really a viable solution.
So in short I see these solutions:
- waiting for Unity to fix the bug.
- finding a different working bloom implementation.
- using a different asset for the procedural clouds that can draw on top of a quad (or asking the asset maintainer).
- using a non-Spine shader on the skeleton (although this will discard some of the vertex-color based features).
Harald wroteSo in short I see these solutions:
- waiting for Unity to fix the bug.
- finding a different working bloom implementation.
- using a different asset for the procedural clouds that can draw on top of a quad (or asking the asset maintainer).
- using a non-Spine shader on the skeleton (although this will discard some of the vertex-color based features).
Alright man, I will keep you updated when Unity gets back to me about the bug report, hopefully they'll be able to handle it. The ugly fix I've done will work for me for now.
Just so we're on the same page, you've checked out both of these new repros including the one I've sent to Unity, right ?
I mean this one https://drive.google.com/open?id=1E6Z8co6Mm7giuqk4-yB6s7AkKL1VHKS_
Carl wroteJust so we're on the same page, you've checked out both of these new repros including the one I've sent to Unity, right ?
I mean this one https://drive.google.com/open?id=1E6Z8co6Mm7giuqk4-yB6s7AkKL1VHKS_
Yes, I checked out both.
Unfortunately Unity QA team is extremely unresponsive. Seems like we can't rely on them for fixing their own engine, neither can fix anything ourselves since it's a black box. Honestly I can't see any other alternative but to abandon the engine at some point because this is a huge technical debt.
I'm sorry that you have to support it because Unity is very popular and there's no way to ignore it. I will keep the temporary workaround as a permanent solution and won't bother you with this anymore.
I'm sorry to hear that they did not respond yet with any fix, I can understand your disappointment :wounded:.
Sometimes it just takes a bit longer until they get to work on the ticket, and suddenly you receive a notification that it's fixed. Unfortunately noone knows whether it will be fixed in the following two months, half a year or never.
I will keep the temporary workaround as a permanent solution and won't bother you with this anymore.
We would also recommend to not rely on a bugfix. No problem at all about bothering us, we are happy to help where we can.