• Unity
  • Custom spine shader

Hi,
we are currently developing a game using URP and are looking into using Spine for our sprite animations, but require to the use of our own shaders as we need to modify the vertex positions of our sprites. In the Basic Platformer example scene, it says that it's also possible to use your own shaders for Spine, given that it fulfils certain requirements and that the Spine-Unity documentation says more about it, but looking at the documentation online there is no mention on how to create your own shaders that support Spine.

Could anyone give me some starting point on what steps are required to write a shader that is compatible with Spine and how to make Spine use it?

Thanks in advance!

Related Discussions
...
  • Düzenlendi

Have a look at this thread...

Use Premultiplied Alpha when texture packing normal maps?

Towards the bottom you'll find a shader graph example using a Sprite Lit Master node, including a vertex displacement shader. I'm assuming the process is the same if you do not plan on using a lit node.

If you need any additional information or help, please ask. Good luck!

Hi, thanks for your answer.
After I posted the question we just straight up tried applying our shader(lit) to a spine objects mesh and it mostly worked fine right out of the gate actually. We just had a bit of problems with the vertex normals which seem to be flipped backwards?

Maybe a more refined question now would be: Are there any caveats with a custom shader or some special things we have to consider when using our own shaders. Do the shaders that come with Spine do anything out of the ordinary? Again, the documentation doesn not really cover this question despite the example scenes telling otherwise...

Linard yazdı

Hi, thanks for your answer.
After I posted the question we just straight up tried applying our shader(lit) to a spine objects mesh and it mostly worked fine right out of the gate actually. We just had a bit of problems with the vertex normals which seem to be flipped backwards?

Maybe a more refined question now would be: Are there any caveats with a custom shader or some special things we have to consider when using our own shaders. Do the shaders that come with Spine do anything out of the ordinary? Again, the documentation doesn not really cover this question despite the example scenes telling otherwise...

Have you tried checking "add normals" and "solve tangeants" in the advanced section of the SkeletonAnimation component? I had flipped normals until I did that.

Thanks for the info that the shaders section of the docs contains no such section. We will add it, an issue ticket has been created:
[unity] Add Writing your own shaders section to docs · #1776
We will let you know once it's done.

Regarding your question: as SquaLLio pointed out, most likely you have not enabled Add normals and Solve tangents at your SkeletonAnimation component. Short documentation on the parameters can be found here:
spine-unity Runtime Documentation: Setting Advanced Parameters

Thanks for letting me now you plan to add such a section. Also enabling "add normals" did solve my lighting problem. Thanks.

Thanks Harald for the info!

Think this part should say "Solve Tangents"?

Spine shaders typically don't need tangents, therefore Advanced - Solve Normals may need to be enabled at your component when using normal maps.

I've been curious as to what is going on behind the scenes with the "Add Normals" and "Solve Tangents" buttons - is it just providing normals/tangents based on the sprite's mesh being "flat"? Like, per vertex? When I'm using the URP/2D/Spine/Sprite shader with normal-maps, it doesn't seem to require either of those options being selected. But in the other thread about shaders (Use Premultiplied Alpha when texture packing normal maps?) Squallio needed to select them for his custom Shader Graph.

Is there much overhead in selecting those? Is that information being generated/used when I select the URP/2D/Spine/Sprite shader regardless of of whether I selected the options or not?

I've made a couple custom shaders by modifying the URP/2D/Spine/Sprite shader - worked great. Now my goal is to be able to make a custom lit shader that supports normal maps, that I can use Shader Graph to create (part of it, at least).

The two ways I see being able to do this would be:

1) Write the entire shader in Shader Graph, and use Unity's Sprite Lit Master Node like Squallio did in that other thread. Would there be a downside to this? (namely, if there is overhead in having to select the Add Normals / Solve Tangents that I could avoid). I'd like to stay as CPU efficient as possible - we have a ton of plant/environment assets that are spine animations that have normal maps.

2) I read that it might be possible to take the shader code generated from Shader Graph, and combine it into the Spine shader? I haven't looked too much into this yet - I see that I can right click nodes in Shader Graph and choose Show Generated Code. It seems to generate somewhat readable HLSL shader code. May need to look into it a bit more, but if this was an option it'd be great.

Thanks!

Sorry for the late reply.

Jamez0r yazdı

Think this part should say "Solve Tangents"?

Thanks very much for the hint, just fixed it!

Jamez0r yazdı

I've been curious as to what is going on behind the scenes with the "Add Normals" and "Solve Tangents" buttons - is it just providing normals/tangents based on the sprite's mesh being "flat"? Like, per vertex?

The data is provided (generated and uploaded to the GPU) per vertex, yes. this is additional data per vertex adding to the already existing data like position, uv, vertex color.

The normals are all simply facing direction (0, 0, -1), so generating them is not much effort.
While the tangents are also "flat" (tangent.z == 0), generating them takes more processing time as it needs to analyse where the +U and +V coordinate axes are pointing in object space. This is needed to interpret the normal map, since the +red channel in the normal map does not point right, it points in +U direction, similar for green channel and +V direction, and +blue channel for +normal direction. The tangents will change when e.g. an animation rotates or even deforms (stretches) an attachment.

Jamez0r yazdı

When I'm using the URP/2D/Spine/Sprite shader with normal-maps, it doesn't seem to require either of those options being selected.

Hm, I don't think that your normal map is applied correctly then. It needs both the normal, which can come from Add normals or from material parameter Fixed normal. The tangents need to be provided though, otherwise undefined vertex data might have been used as tangents?
Did you test what changes when providing tangents and normals? I would be surprised if it applied the normal map correctly before.

Jamez0r yazdı

1) Write the entire shader in Shader Graph, and use Unity's Sprite Lit Master Node like Squallio did in that other thread. Would there be a downside to this? (namely, if there is overhead in having to select the Add Normals / Solve Tangents that I could avoid). I'd like to stay as CPU efficient as possible - we have a ton of plant/environment assets that are spine animations that have normal maps.

There is no basic downside in using Shader Graph, as it's just a code generator. You should be able to add (or create custom) shader nodes yourself in case you see some functionality missing, like providing a fixed normal as input instead of using the standard vertex normal. You still have to provide tangents when using normalmaps. Well, actually you could deduce tangents in the fragment shader using the derivative functions ddx() and ddy() on both position and texcoords. If you cannot find any reference online, I can dig out some shader code and post it here for reference if you like.

Anyway, please always perform some measurements with Solve Tangents enabled vs disabled, otherwise your efforts might be on the wrong topic. If you mind to share, it would be nice to see your real-world values of how much enabling Solve Tangents really costs.

Jamez0r yazdı

2) I read that it might be possible to take the shader code generated from Shader Graph, and combine it into the Spine shader? I haven't looked too much into this yet

Yes, basically you can of course always combine generated code with your existing hand-written one. You just have to understand what each function call does and combine and adjust it accordingly. Finding all variable and method definitions of included files may be the more labour-intensive part of it.

Thanks for the info Harald!

Hm, I don't think that your normal map is applied correctly then. It needs both the normal, which can come from Add normals or from material parameter Fixed normal. The tangents need to be provided though, otherwise undefined vertex data might have been used as tangents?
Did you test what changes when providing tangents and normals? I would be surprised if it applied the normal map correctly before.

I went back and looked at how I had it set up, and I had forgotten that I WAS using Solve Tangents. So thanks a lot for that info because I had totally forgotten (my teammate is setting up the normal maps now, so I'm really glad you mentioned that because I wasn't telling him to check that box).

However, I wasn't using "Add Normals" on the SkeletonAnimation, or "Fixed Normals" on the Material - but I was exporting my Normal Maps with the y-axis flipped. Somehow this seems to end up with very similar results. Probably just a default orientation sorta thing.

I also just tested out using "Fixed Normals" on the shader, with only "Solve Tangents" selected on the SkeletonAnimation (and with a normalmap that didn't flip the y-axis) and I think it does look slightly better than the other options? I saw the tooltip on it said that its cheaper than "Add Normals" and could look better, haha

So I'm thinking that my forward path will be to use Fixed Normals on the shader, and Solve Tangents on the SkeletonAnimation, and to NOT flip the y-axis on my normal maps.

There is no basic downside in using Shader Graph, as it's just a code generator. You should be able to add (or create custom) shader nodes yourself in case you see some functionality missing, like providing a fixed normal as input instead of using the standard vertex normal. You still have to provide tangents when using normalmaps. Well, actually you could deduce tangents in the fragment shader using the derivative functions ddx() and ddy() on both position and texcoords. If you cannot find any reference online, I can dig out some shader code and post it here for reference if you like.

Awesome! I'm messing around with the same sort of thing Squallio did in that other forum post, testing shadergraph using unity's "Sprite Lit Master" node. The lighting seems to be working identically to the Spine shader, woohoo 8) 8)

5 gün sonra
Jamez0r yazdı

I also just tested out using "Fixed Normals" on the shader, with only "Solve Tangents" selected on the SkeletonAnimation (and with a normalmap that didn't flip the y-axis) and I think it does look slightly better than the other options? I saw the tooltip on it said that its cheaper than "Add Normals" and could look better, haha

Hm, it's actually a bit strange that there are any differences, as the Fixed Normal should point in the exact same direction as all Add Normal vertex normals. The Fixed Normal Space matters of course, so perhaps it's different because it's slightly tilted in respect to the camera forward axis or something like that. Anyway, as you said it's better to use Fixed Normals instead of Add Normals when your shader supports it.

Jamez0r yazdı

So I'm thinking that my forward path will be to use Fixed Normals on the shader, and Solve Tangents on the SkeletonAnimation, and to NOT flip the y-axis on my normal maps.

This sounds good. It's a pain that there are multiple normalmap Y standards, so always beware when exporting from multiple applications or sources.

Jamez0r yazdı

The lighting seems to be working identically to the Spine shader, woohoo

Glad to hear! 8)