• Unity
  • Sprite Shaders for Unity

Argh thats just because you're not on Unity 5.5.

Its only a warning about the SpriteDepthNormalsTexture shader which you prob won't be using - the rest of the shaders will be uneffected 🙂

@dothem sorry must've missed your post - what do you mean by 'normale sprite'? Like a sprite with a normal map?
The shaders should work on mobile and with spine animations.

Related Discussions
...
ToddRivers wrote

Argh thats just because you're not on Unity 5.5.

Its only a warning about the SpriteDepthNormalsTexture shader which you prob won't be using - the rest of the shaders will be uneffected 🙂

@dothem sorry must've missed your post - what do you mean by 'normale sprite'? Like a sprite with a normal map?
The shaders should work on mobile and with spine animations.

Yes, I can't upgrade now, not all of the assets I'm using are 5.5 compatible. 😢

Yet, previous version worked like a charm. It's not really a warning, the shader doesn't compile at all. What should I change to solve the issue?

@[deleted]
UNITY_VERTEX_INPUT_INSTANCE_ID should be UNITY_INSTANCE_ID in Unity 5.4
Should be easy to find it in the shader code and replace it.

The spine-unity bundled version has this change.

You can also delete that shader if you want, like I said I very much doubt you're using it (it's only used to render a Depth+Normals texure for effects like ScreenSpace Ambient Obscurance).

It really shouldn't matter even if it doesn't compile - its not referenced by the main sprite shaders.

Thank you 🙂
I'll test the new shaders tomorrow 🙂

Thanks again for your work!

No worrie 🙂 Fingers crossed that's finally sorted your vertex lighting normals problems!

Yep, normal map. But without Spine (normal Sprite with material). This won't rendered on mobile. But the Spine object do.

Pharan wrote

@[deleted]
UNITY_VERTEX_INPUT_INSTANCE_ID should be UNITY_INSTANCE_ID in Unity 5.4
Should be easy to find it in the shader code and replace it.

The spine-unity bundled version has this change.

Thanks, that fixed all the errors (there were more than one).

About the normals, now (with the version of yesterday) work only if:

Pixel lit, write to depth on, (0,0,-1)

Vertex lit, (0,0,1)

if I flip the normals, they're no longer lit, in both cases.

Also, the pixel lit one looks way darker than the vertex lit. Is that normal?
I'm using the vertex lit shaders so having all of the normals to (0,0,1) it's just fine for me, yet, it's a bit weird.

Hmm thats not good. The pixel shader being dark was another bug I forgot to fix when I last checked in doh - I wasn't clamping the dot value for lights, that's fixed in latest.

I've attached an example project showing pixel lighting, vertex lighting and unity's standard shader side by side.
In it the mesh normals are set to (0,0,-1) and the lighting looks correct (for me at least!)

And if you set the normals to (0,0,1)...

Its worth opening it and seeing what it looks like for you.

ToddRivers wrote

Hmm thats not good. The pixel shader being dark was another bug I forgot to fix when I last checked in doh - I wasn't clamping the dot value for lights, that's fixed in latest.

I've attached an example project showing pixel lighting, vertex lighting and unity's standard shader side by side.
In it the mesh normals are set to (0,0,-1) and the lighting looks correct (for me at least!)

And if you set the normals to (0,0,1)...

Its worth opening it and seeing what it looks like for you.

Unfortunately you're using 5.5 (which I still consider too early to adopt since they did a lot of changes and devs from the asset store are generally waiting a bit before supporting it fully) and I'm still on 5.4.2f2 so the import of the project didn't go as expected...

Anyway, the last version fixed the pixel lighting.

Still, pixel lighting is ok on 5.4.2f2

but

vertex lit has its normals inverted (only works with 0,0,1)

yet

if I enable rim lighting with (0,0,-1) on vertex lit, I get almost a perfectly lit skeleton. The higher the power, the better.
With the same settings if I later switch to (0,0,1) the material gets fully white (rim color) doesn't matter the rim power value.

So, whatever lighting calculation you make to get rim lighting, assume an infinite power and that should work with vertex lighting as well with proper normals (0,0,-1)..
Or, rim lighting inverts the normals again, I don't know :-/

Gah forgot your not on 5.5.
Is anyone else on 5.5? Can anyone confirm the normals work as expected for them?

It's possible that for some reason UNITY_REVERSED_Z isn't defined when using vertex lighting in 5.4 on android (thats the platform your running right?). That seems super weird / unlikely but running out of ideas.
If that is the case then that's a bug with Unity and not something I can really fix, I will try and check android on 5.5 at somepoint to make sure it's not a prob with that as well.

ToddRivers wrote

Gah forgot your not on 5.5.
Is anyone else on 5.5? Can anyone confirm the normals work as expected for them?

It's possible that for some reason UNITY_REVERSED_Z isn't defined when using vertex lighting in 5.4 on android (thats the platform your running right?). That seems super weird / unlikely but running out of ideas.
If that is the case then that's a bug with Unity and not something I can really fix, I will try and check android on 5.5 at somepoint to make sure it's not a prob with that as well.

This implies you're going to support only the very latest unity version, that's a pity 🙁

Is the version shipped with the runtimes by Esoteric going to only support 5.5 as well?

In general we aim to officially support the latest version of each game toolkit. It nearly doubles our workload to also support the penultimate version. That said, unofficially the latest runtimes usually continue to work on recent previous versions of the game toolkits. There is also the option to freeze your runtime and editor versions.

Pharan wrote

@[deleted]
That seems right.
UNITY_REVERSED_Z is in the 5.5 documentation (https://docs.unity3d.com/550/Documentation/Manual/SL-BuiltinMacros.html)
but not in 5.4 (https://docs.unity3d.com/540/Documentation/Manual/SL-BuiltinMacros.html)

Yup, I don't know if it has any impact on the shaders, but with 5.5 (and I suppose starting from 5.5) the depth buffer is inverted.

From the ChangeLog:
"Graphics: Improve shadows precision for large game worlds. Use reverse-float depth buffer for improved depth buffer precision on modern GPUs. Particularly improves directional light shadowing for large view distances.​"
"Graphics: Added bool SystemInfo.usesReversedZBuffer to be able to know if the platform is using a "reversed" depth buffer."

Probably some useful info from the upgrade guide to 5.5:
https://docs.unity3d.com/Manual/UpgradeGuide55.html

Shaders: Z-buffer float inverted

The Z-buffer (depth buffer) direction has been inverted and this means the Z-buffer will now contain 1.0 at the near plane, 0.0 at the far plane. This, combined with the floating point depth buffer significantly increases the depth buffer precision resulting in less Z-fighting and better shadows, especially when using small near planes and large far planes.

Graphics API changes:

Clip space range is [near, 0] instead of [0, far]
_CameraDepthTexture texture range is [1,0] instead of [0,1]
Z-bias is negated before being applied
24 bit depth buffers are switched to 32 bit float format
The following macros/functions will handle reversed Z situations without any other steps. If your shader was already using them, then no changes needed from your side:

Linear01Depth(float z)
LinearEyeDepth(float z)
UNITY_CALC_FOG_FACTOR(coord)
However if you are fetching the Z buffer value manually you will need to do write code similar to:

float z = tex2D(_CameraDepthTexture, uv);
#if defined(UNITY_REVERSED_Z)
z = 1.0f - z;
#endif
For clip space depth you can use the following macro. Please note that this macro will not alter clip space on OpenGL/ES plaforms but will remain [-near, far]:

float clipSpaceRange01 = UNITY_Z_0_FAR_FROM_CLIPSPACE(rawClipSpace);
Z-bias is handled automatically by Unity but if you are using a native code rendering plugin you will need to negate it in your C/C++ code on matching platforms.

Unity 5.6: right is now left!

Nate wrote

Unity 5.6: right is now left!

Pretty much 😃

little update: on 5.4 vertex-lit shaders work correctly with (0,0,-1) also if you add a normal map (correctly lit from the front)

so, if I use either a normal map or rim lighting all is fine.
If the shader is flat and "simple", its lighting gets inverted.

Could this help to spot the issue? It's really weird the lighting is flipped only when there is not a normal map and there's not rim lighting activated.

I don't understand why Unity devs love to change sometimes names for code methods. It's like they love to mess projects up haha.

Anyways, I have a question. Is there a way to have the additive blending from Spine to work with your shaders @ToddRivers?
If I use additive blending in Spine that attachment doesn't work with your shaders. It would be awesome to combine both of them so I can animate lit things. Something I could do would be to animate the emissive power in your shaders to animate the lighting on my character, or something like that.

additive blending on the same shader is a premultiplied-alpha trick.
It probably will never work combined with various other lighting and shader features, so you may have to set a separate additive material specific to that slot/attachment. Note that this will necessarily break dynamic batching.

I think animating the Emissive Power property is fine. Are you not able to do that?

@Pharan what do you mean by setting a separate additive material specific to that slot/attachment? You mean inside Spine or in Unity?
Also I haven't tried to animate the emissive power yet so I can't tell if it works or not.

@Pharan doh! I didn't realise that. Yeah guess thats it... Its weird it works for Pixel-lighting though, both use the same function to work out normals direction so would expect both to be wrong.

@NeatWolf yeah its too much work to keep the latest version of the shaders working with multiple versions of unity. In general you can grab older revisions of the shaders that were built against older versions of Unity however yeah I'm not going to be trying to fix bugs for multiple versions of Unity at the same time. I'd try and push for your other assets to support latest Unity instead 😉
I am totally confused by why having a normal map or rim lighting makes it different, there's two functions calculateSpriteWorldNormal and calculateSpriteViewNormal in SpriteLighting.cginc that calculate the normals which is what effects the lighting.
The only thing of note in them is that UNITY_REVERSED_Z define that flips Z on certain platforms - rim lighting and normal maps shouldn't have any effect on it, plus there should be no difference between the two lighting modes.
Its all very strange!

You are on Android yeah? I am slightly scared it might be a weird android thing thats might still be there in 5.5. Need to check that!

ToddRivers wrote

Gah forgot your not on 5.5.
Is anyone else on 5.5? Can anyone confirm the normals work as expected for them?

It's possible that for some reason UNITY_REVERSED_Z isn't defined when using vertex lighting in 5.4 on android (thats the platform your running right?). That seems super weird / unlikely but running out of ideas.
If that is the case then that's a bug with Unity and not something I can really fix, I will try and check android on 5.5 at somepoint to make sure it's not a prob with that as well.

@[deleted]

Works for me on 5.5.0f3
I just tested (0,0,1) on vertex lit. But I can see it looks the same as your test :party:

Image removed due to the lack of support for HTTPS. | Show Anyway

Thanks for the continued support!

AlaNintendo wrote
ToddRivers wrote

Gah forgot your not on 5.5.
Is anyone else on 5.5? Can anyone confirm the normals work as expected for them?

It's possible that for some reason UNITY_REVERSED_Z isn't defined when using vertex lighting in 5.4 on android (thats the platform your running right?). That seems super weird / unlikely but running out of ideas.
If that is the case then that's a bug with Unity and not something I can really fix, I will try and check android on 5.5 at somepoint to make sure it's not a prob with that as well.

@[deleted]

Works for me on 5.5.0f3
I just tested (0,0,1) on vertex lit. But I can see it looks the same as your test :party:

Image removed due to the lack of support for HTTPS. | Show Anyway

Thanks for the continued support!

It looks like my situation but with (0,0,-1) normals in all three cases 😃

Anyway you're not targeting Android there, as I can see by looking at the window title.

Could you please test it by also switching the build platform to Android?

I tested again on Android (mobile phone) with the newest Shaders. Materials with PixelLit won't be rendered when its not a SpineObject. When i run it on desktop (android build) it's displayed and works correctly.

Hmm weird, is that only when using a Sprite Renderer? If you just apply that material to a quad is it the same / does it render?

Unity's own sprite system doesn't really like custom materials so could be something in that thats conflicting.

Guys, if you're using ToddRivers' version of the shaders and the latest spine-unity.unitypackage, make sure you delete the Sprites shaders in the Modules/Shaders folder. I'm not sure but their cginc files might conflict.

Yep, rendered on cube. I tested it again with 5.4 Unity, and there it works. So there must be something changed in 5.5

@dothem Hey so I just checked the shaders out on android and it all works for me ALTHOUGH - do check what your pixel light count is when running the game I reckon that will be whats making pixel lighting not work for you.

Go to Quality settings inside of Project Settings.
For each of the quality settings (Fastest/Fast/Simple etc) check the pixel light count.
If its zero then pixel lighting won't work, and you should use Vertex lighting instead. Less than 4 means less lights will effect objects than when using vertex lighting so it will look noticeably different.

Android /mobile tends to pick a faster quality setting than when you run the build on your PC so there might be lighting differences.
Vertex lighting is recommended for mobile because of this (its cheaper to do).
It would be nice to automatically switch shaders when pixel lighting is disabled but not sure there is.

Hey. I'm trying to use volumetric in my project.
I'm having difficulty with the imposition on the volumetric character.
Character appears transparent and looks nice smooth edges. Either the light is working properly, but the character at the same time gets rough edges.

I tried all the options of the shader settings could find. However, the ideal solution is not found.
Please help find a solution that will help to get smooth edges and realistic behavior of light.

The following video shows the essence of the problem.

@xcube That's because Volumetric lighting depends on the depth buffer, you can't write soft edges to the depth buffer, a pixel is either written at its depth or not written - fading doesn't really make sense physically.

However!! I did manage to write a custom camera replacement shader that allows just that - writing soft edge to the depth buffer, its actually on my github:
https://github.com/traggett/UnitySpriteShaders/blob/master/SpriteShaders/SpriteDepthNormalsTexture.shader
Using that you can generate a depth+normals texture for a camera that allows you to use effects like Depth of Field or Volumetric Lighting without having to write to depth when rendering sprites (the sprites get written to the depth texture afterwards, with soft edged alpha).

Anyways! I'm away for a bit but though I'd leave peops with a christmas present - I've added Specular maps to the shaders :sun:
It was a hell of a lot more work than I'd imagined - I fell down the rabbit hole somewhat pulling apart how Unity's new shaders do their physics based specular effects but managed to get it workign with the sprite shaders.
Specular effects are optional (so wont effect shaders performance unless you enable them) and are based on the Metallic workflow for shiny materials using a Metallic Gloss Map as explained by the first chart here:
https://docs.unity3d.com/Manual/StandardShaderMaterialCharts.html

@ToddRivers Thank you very much for your help!
But I was not able to apply your shader SpriteDepthNormalsTexture.shader camera. I'm not a great expert in this field.

Nevertheless, I tried to create your shader and script UseShade.cs

public class UseShade : MonoBehaviour {

public Camera custom_CAMERA;
public Shader myShade; 
  
void Start () {
      custom_CAMERA.RenderWithShader(myShade, "_forVol");
}
}

But it did not change anything in the scene. What am I doing wrong? :S
If it is interesting to test the project spread. (Unity5.5.0f3)
https://drive.google.com/open?id=0B3A2ZpysfaxBNm9MaXRlY3lUSjg

4 days later
ToddRivers wrote

@[deleted] That's because Volumetric lighting depends on the depth buffer, you can't write soft edges to the depth buffer, a pixel is either written at its depth or not written - fading doesn't really make sense physically.

However!! I did manage to write a custom camera replacement shader that allows just that - writing soft edge to the depth buffer, its actually on my github:
https://github.com/traggett/UnitySpriteShaders/blob/master/SpriteShaders/SpriteDepthNormalsTexture.shader
Using that you can generate a depth+normals texture for a camera that allows you to use effects like Depth of Field or Volumetric Lighting without having to write to depth when rendering sprites (the sprites get written to the depth texture afterwards, with soft edged alpha).

Anyways! I'm away for a bit but though I'd leave peops with a christmas present - I've added Specular maps to the shaders :sun:
It was a hell of a lot more work than I'd imagined - I fell down the rabbit hole somewhat pulling apart how Unity's new shaders do their physics based specular effects but managed to get it workign with the sprite shaders.
Specular effects are optional (so wont effect shaders performance unless you enable them) and are based on the Metallic workflow for shiny materials using a Metallic Gloss Map as explained by the first chart here:
https://docs.unity3d.com/Manual/StandardShaderMaterialCharts.html

Can't say it enough, but you sir are a god! Thanks so much for falling down the rabbit hole. We all definitely appreciate it.

Have a great winter break and early happy new year! :party:

Hi there!

I was wondering if there is an easy way to colorize differently several Spine Skeletons instances of the the same Prefab, without causing all the contained materials in the MeshRenderers to automatically create a separate instance of each material for each SpineSkeleton?

Is there any workaround for this? (excluding having skins colored differently of course - last resort)
I have several skeletons in the scene and I fear that colorizing each material individually could compromise performance.

5 days later

Hey everyone, happy new year!

I've, just checked in some updates to how fixed normals work - you can now specify them either in camera space or model space and adjusting for lighting back faces now works correctly (there were a couple of bugs with it).
However correct back face lighting now requires mesh normals (its the only way the shader can know what direction a vertex is facing in).
The shader does now remind you what it wants in terms of tangents or normals though 🙂
If you grab latest you might need to retick 'use fixed normals' on your materials as the defines have changed, sorry!

The majority of the time with Spine animations you don't need to adjust the tangents for correct back face lighting - it's needed only when you have rotated your object to face away from the camera and thus the tangents need to be flipped in the shader.
I recommend instead of rotating sprites, use the Spine skeleton.FlipX/Y. This means your Spine animation won't need normals and things like Z offset for submeshes will stay correct.

If you render Unity Sprites or Meshes then you might need to turn on the 'Adjust Backface Tangents' option if they face away from the camera.


03 Jan 2017, 12:39


@[deleted] yeah using a custom Depth+Normals buffer is pretty advanced to be fair.
What you're doing there is correct - that should render the depth+normals for the scene including soft alpha'd sprites.
However you want to render into a RenderTexture which you can then pass through to your Post Effects. (ie give the camera a target texture).

You will also need to edit the PostEffect shaders you're using to use this newly created RenderTexture instead of the default camera Depth+Normals texture.
Admittedly this is all pretty advanced stuff and you'll need to be able to edit your post effects shaders to get it to work but it's what I do for my game so def works 🙂

I recommend reading this (plus the first 2 parts) which explains the CameraDepthNormals texture and how it gets used with a simple example.
http://willychyr.com/2013/11/unity-shaders-depth-and-normal-textures-part-3/
In this example he's telling his camera to render a depth+normals texture for him with the following line of code:

camera.depthTextureMode = DepthTextureMode.DepthNormals;

Then his post effect shader is using that texture with:

_CameraDepthNormalsTexture

Which inside a unity shader automatically grabs the last cameras generated DepthNormals texture.

In your case you don't want to generate a texture or use _CameraDepthNormalsTexture as you've rendered your own special one. So instead of using _CameraDepthNormalsTexture in the shader, pass it the texture you rendered into with
camera.RenderWithShader() and you should see the normals and depth for your Sprites.
This can then be adapted for things like Depth of Field or SAAO.

Happy new year!
Thank you for your help and information. I will try to apply it in practice.

Cool, good luck! If you want to use it for a Post Effect that just uses the Depth Buffer (Like I think Unity's built SSAO now does) then I've added a shader that renders a custom depth buffer for a camera with nice soft edges for sprites that don't normally write to depth:
https://github.com/traggett/UnitySpriteShaders/blob/master/SpriteShaders/SpriteDepthTexture.shader:

However aswell as changing references to _CameraDepthTexture in the post effect shader to be your own depth texture you will also need to use DecodeFloatRGB() instead of SAMPLE_DEPTH_TEXTURE() to get a depth value from the texture (SAMPLE_DEPTH_TEXTURE uses 32bit RGBA for depth, we have to use just 24bit RGB because we're using the alpha channel to blend the soft edges).
DecodeFloatRGB() is inside ShaderMaths.cginc.

5 days later

@ToddRivers,

I'm playing around with the new specular map option. Super cool stuff man! !

Just letting you know, I haven't had any trouble with it on 5.5.0f3. 🙂


09 Jan 2017, 09:02


@ToddRivers
Hi ToddRivers, do you have this performance spike when you are using pixel lit, sprite?

Image removed due to the lack of support for HTTPS. | Show Anyway