Arzola

I'm currently using Unity (in case it makes any difference for the following), and I wish to give the exported characters some additional depth, as my goal is to use a perspective camera.

I was wondering if anyone could help me answer the following questions:
1 - Would there be any downsides for me to programmatically set the zSpacing of Spine models to values that fall outside the inspector clamped [-1 to 0] range?
2 - Is it possible to rotate individual bones on the z axis? I don't really expect to change this that much, or as granular as a per-animation basis, just wondered if it was possible, so that there was some more variety with the light that bounces of models.
3 - Not really pivotal, but any suggestions to give some depth to the characters from their side view? As expected, since the mesh is drawn on planes, watching a character from the side would reveal they have no depth. And given how there is no magic button to extrude a model at runtime (this being the simplest form of depth I can think of), I wanted to know if anyone has a suggestion.

Thank you in advance, and have a nice day.
Arzola
  • Сообщения: 11

Harald

Arzola писал(а):1 - Would there be any downsides for me to programmatically set the zSpacing of Spine models to values that fall outside the inspector clamped [-1 to 0] range?
No, that's perfectly valid. You might e.g. want to set it to +1 after rotating it around the vertical axis by 180 degrees.
Arzola писал(а):2 - Is it possible to rotate individual bones on the z axis? I don't really expect to change this that much, or as granular as a per-animation basis, just wondered if it was possible, so that there was some more variety with the light that bounces of models.
Technically it is possible by modifying the provided spine-unity source code. However you might not really want to edit the MeshGenerator unless you know what you're doing.

You can use normalmaps as provided by the Spine/Sprite shader to make light interaction more interesting, which is far easier than modifying mesh generation code.
Arzola писал(а):3 - Not really pivotal, but any suggestions to give some depth to the characters from their side view? As expected, since the mesh is drawn on planes, watching a character from the side would reveal they have no depth. And given how there is no magic button to extrude a model at runtime (this being the simplest form of depth I can think of), I wanted to know if anyone has a suggestion.
The shaders that come with the spine-unity runtime don't provide for it, but theoretically true displacement mapping (which will generate additional vertices and offset them) in conjunction with height maps could make a flat skeleton more three-dimensional. You could have a look if you can find some suitable displacement mapping shaders, then be sure to export the skeleton atlas texture again with Straight alpha workflow (Premultiply alpha setting disabled and Bleed enabled).

How exactly do you want to show the skeleton from the side? Could you provide some screenshots that depict what you are trying to achieve?
Аватара пользователя
Harald

Harri
  • Сообщения: 2769

Arzola

Thank you for taking your time to respond.
Harald писал(а):Technically it is possible by modifying the provided spine-unity source code. However you might not really want to edit the MeshGenerator unless you know what you're doing. You can use normalmaps as provided by the Spine/Sprite shader to make light interaction more interesting, which is far easier than modifying mesh generation code.
Alright, I'll look at the script you pointed out, thanks.

Maybe pointing out the light aspect of it was out of place, it's not the only reason I wanted to rotate the bones. My main idea was to rotate the bones on the pivots so that they would "touch" the following layer while rotated, giving the impression the model is segmented, but tied together, like a paper doll (how I would organize the workflow and order layers is something for me to figure out). Something minor but present, without anything drastic like going full 90 degree rotations, if it came to that, I'd just do 3D animations.

I understand it sounds overkill, and not really something meant to be part of the core Spine runtime, so I'll give it a try based on what you pointed out. Once again, thanks.
Arzola писал(а):How exactly do you want to show the skeleton from the side? Could you provide some screenshots that depict what you are trying to achieve?
I didn't want anything drastic really, just something akin to a basic extrude to give the depth of paper (if anything maybe slightly thicker so it's side-view visible). It only needs a small amount of depth for this, so I don't really care that much for how the side faces would look. "Not invisible on the side" being pretty much what I'm looking for.
Arzola
  • Сообщения: 11

Harald

Arzola писал(а):My main idea was to rotate the bones on the pivots so that they would "touch" the following layer while rotated, giving the impression the model is segmented, but tied together, like a paper doll
Now I think I know what you want to achieve, thanks for the explanation! At first I thought you wanted to rotate the attachment vertices along the bone (sideways). Rotating it to bridge the gap between "layers" might be a bit tricky. I would still suggest adapting the MeshGenerator code. But instead of rotating the bone, I would suggest just offsetting the vertices in depth (Z direction) depending on how close they are to the start of the bone (current bone location) vs how close they are to the end of the bone (first child bone location perhaps, this might be trickier). So that depth would be:
float ratio = vertexDistanceToBonePos / boneLength;
ratio = clamp01(ratio);
float z = lerp(currentLayerZ, nextLayerZ, ratio);
Hope this helps. :)
Arzola писал(а):I didn't want anything drastic really, just something akin to a basic extrude to give the depth of paper (if anything maybe slightly thicker so it's side-view visible). It only needs a small amount of depth for this, so I don't really care that much for how the side faces would look. "Not invisible on the side" being pretty much what I'm looking for.
Good queston. If it's not seen from a 90 degree angle, it could definitely be done without true displacement mapping. Shader based solutions would be to use a shader with Parallax Mapping or Parallax Occlusion Mapping (POM, though that might be overkill), using a height map that has a narrow gradient at the border from 0 to 1 (and with all inside regions at height 1). When using POM, I think it could also be a steeper 0-1 slope of only 1 pixel width.
Аватара пользователя
Harald

Harri
  • Сообщения: 2769

Arzola

Thank you for your reply.
Harald писал(а):
float ratio = vertexDistanceToBonePos / boneLength;
ratio = clamp01(ratio);
float z = lerp(currentLayerZ, nextLayerZ, ratio);
Yea this seems far more approachable than modifying bone rotation, thank you for the idea.

I'm currently in the middle of that implementation, the idea I currently have involves bone names. And would like to hear some feedback (and am also writing this down, to give anyone that potentially stumbles with this thread some ideas in the scenario they also want to do something equally overkill).

Basically, to do what I described before, I might need to semi discard the default draw order.

Let's say you have a simple character, a torso, four limbs, and the head. And for the specific look of this character, I want the torso to be the bottom element, where the rest would sit on top of it. Draw order presents an issue for the vertex offset idea, because while as it stands, while I really don't care for the draw order of the non-torso elements (if left arm is above head, etc), if I was to respect the original implementation, z position would be calculated by [drawOrder * zSpacing], so only one of the pieces would be "connected" to the torso, where the rest would be on top of it, but "floating", there will be a gap to the torso determined by [(drawOrder-1) * zSpacing].

If zSpacing is small, it really won't matter, as it would be fairly difficult to view anyway. But if I was to separate the parts, then that gap will start to pile up the more items to draw there are (meaning the "max" draw order position gets larger).

So my idea was to label bones/slots based on the height I would like them to be rendered at. For the previous example, it would mean labeling the bones something like "0-torso" , "1-left-arm", "1-right-arm", "1-left-leg", "1-right-leg", "1-head". That way, on the mesh generator, I can get the bone name of an attachment and determine if I should render it "traditionally" (the default spine way) if there is NOT a number, or do it via a custom way where I can clamp positions based on that number.

The two challenges I can think of will include:

z fighting, for which I might need to add a secondary zSpacing with a smaller magnitude that actually does make use of draw order.

And changing draw order mid animation (I don't use this option that much, but it might be troublesome when I do need it), let's say I want an arm to go behind the head and torso, a "-1" bone number, I might need to listen to some custom events to change a bone's name during runtime or an equivalent.

There's also the handling of bones that are just points (start = end), I might need to do some special bone names to determine how to draw these (could be something as simple as distance from bone, etc., might need a couple types).

Tweaking all this might gonna need a bit of work, but I think the end look will be worth it.

EDIT: I realized this could all be solved if I could bundle the draw order items into folders, and had a toggle to mark the items within the folder as the "same level". I'm not going to do something as selfish as request this to be a feature, I just thought another solution could be for me to edit the exported jsons to do something to this effect.

EDIT 2: After playing around with the unity mesh generator and seeing how the draw layers are exported to JSON, I noticed all draw layers are p much done sequentially based on priority already, so I might be able to get away with something really simple: draw order "markers". If I add items in the draw order hierarchy (tied to small, 1x1 transparent elements or something), I could start labelling these with "--GROUP_START" and "--GROUP_END" or tags to this extent, and read that on the mesh generator to set flags to increase or keep the current z "height". This should also take care of the runtime order change issue I mentioned before automatically, all depending if an element is before or after these tags.
Arzola
  • Сообщения: 11

Harald

Arzola писал(а): If I add items in the draw order hierarchy (tied to small, 1x1 transparent elements or something), I could start labelling these with "--GROUP_START" and "--GROUP_END" or tags to this extent, and read that on the mesh generator to set flags to increase or keep the current z "height".
This sounds like a reasonable approach. I was going to point out that the SkeletonRenderSeparator adds slots just to mark the beginning of separate regions, but I guess you already know that.

All in all I don't quite understand what problem you are having and want to solve with discarding the base z depth and assigning a new one? As long as you only increase depth to a fraction less than the next z depth, nothing should go wrong. If you should encounter z fighting because you've moved the attachment at the end of a bone too close to the next layer, you have to decrease the offset anyway, different grouping will rather not solve this issue.
Аватара пользователя
Harald

Harri
  • Сообщения: 2769

Arzola

Harald писал(а):All in all I don't quite understand what problem you are having and want to solve with discarding the base z depth and assigning a new one?
Oh no no, my mistake for not clarifying it properly, what I listed wasn't so much a list of issues I was currently having, but more like "if anyone wants to do this, don't forget to look out for this". Thanks to your pointers it is working as intended. At this point I'm pretty much pseudo documenting in case anyone wants to try doing something similar.

I ended up using something fancier than the distance from the origin position to calculate the final z value, a simple projection:
// The following stems from having a) The slot bone origin position b) That bone's rotation c) That bone's length
// d) The position of the vertex you're currently getting the Z value for
// (we are assuming all of these values are already in the same units)

// Getting the bone tip position (just in case you need it).
boneTipPos.x = boneOriginPos.x + (Mathf.Cos(boneRotation * Mathf.Deg2Rad) * boneLength); // Deg2Rad is a constant, around 0.01745
boneTipPos.y = boneOriginPos.y + (Mathf.Sin(boneRotation * Mathf.Deg2Rad) * boneLength);

Vector2 bonePath = boneTipPos - boneOriginPos;
Vector2 boneOriginToVertexPath = vertexPos - boneOriginPos;

float boneProgressRaw = Vector2.Dot(bonePath, boneOriginToVertexPath) / bonePath.magnitude;
float boneProgress = 1 - Mathf.Clamp01(boneProgressRaw / boneLength); // Here you might want to remove the "1 -", all depends on if you want the tip of the bone to be closer or further away. Also note this takes care of negative values as well.
This allows for the z values to uniformly grow or decrease according to the direction of the bone origin to the bone tip.

Doing it this way allows you to, for example, have "draw bones" for your slots, bones that won't ever be animated directly, but hold your slots and can be tweaked to go beyond or cut short from the ends of an image, to give different levels of depth.

As for the spine side of things, I have a transparent 1x1 image that I just use to make a couple extra slots, which depending on their name initials give additional instructions for the new z value. In my case, I made special flags that allowed to "group" slots, to reset the z level counter (i.e., I have two eyes I want on the same z level), or to quickly move things one level up or down.

image_2021-02-19_144127.png


These flags made it very easy to tweak some things so that they don't look that far away, and the "draw bones" gave an extra level of z-granularity.

I wanted to show a final result, but I'm still midway on finishing a shader that will make the changes in z depth more evident.

But all in all, really, thank you for your pointers.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Arzola
  • Сообщения: 11

Harald

Cool, thanks for the detailled writeup! Glad to hear it's going well! 8)
Аватара пользователя
Harald

Harri
  • Сообщения: 2769


Вернуться в Runtimes