#URP 2D - Renderer feature and Y pivot sorting

1 messages · Page 1 of 1 (latest)

normal elm
#

Hello there! I'm trying to create a "highlight" feature that basically change the color of the character with a specific layer.

Since I have multiple different materials and some of them are not editable without copying them entirely (like Spine ones) I'm using Renderer Feature from URP (for 2D).

So far so good,** everything works fine except one thing** : I can't make the 2D sorting works properly whenever my shader is applied through the renderer feature.

From what I understand after long tests : since I'm hooking on specific moments of the pipeline After rendering transparents, the natural sorting order is ignored by Unity. Also, since I'm just "redrawing" => basically there is no information on sorting. Unity just redraws whatever I tell him to redraw

I have read a ton of documentation about it but can't figure out how to keep Y sorting or if it's even possible.

With the highlight feature off (first screen) everything is pretty good, nice Y sorting etc.
With the highlight feature on (second screen) my highlight works, but Y sorting is broken.

Message is too long so code and shader is included in linked files, sorry for that 🙁

If you have any hints, clue or whatever, I'll take them! Thanks you

sacred osprey
#

So what's the idea with this shader? You're just overriding material if it's selected, and you're doing it through pipeline scripting? Why not just do the material swap by component/interface check?

#

If you're trying to partially change the object if it's behind another sprite, I could see the purpose.

#

In any case, I actually ran into a similar issue with y-sorting before which I resolved by just using 2.5D and using depth without having to rely on unity's sorting.

#

If you are trying to do behind-object silhouette masking then it may be wise to use sprite masks or stencils with a double sprite renderer.

normal elm
#

Hello @sacred osprey, the main idea is to highlight any sprite (or entity since I use Spine) using kinda generic shader to do so.

This way I don't have to write all existing materials to match it. I'd also like to specifically show properly the part visible behind the sprite and to partially show the part invisible currently behind the sprite (like transparency with a lower Alpha, so we visually understand that's its behind)

So what's the idea with this shader? You're just overriding material if it's selected, and you're doing it through pipeline scripting? Why not just do the material swap by component/interface check?

because in this case it's a highlight so basically I thought that it'd be nice to just swap the layer on hover and let the renderer pipeline handle anything else. Just swapping the material won't work for other things like lightning (typically because Spine has more specific shaders)

#

in fact, same question might be asked if I was doing an outline effect : specific things BEHIND the sprite in front shouldn't be visible either

sacred osprey
#

Right, I kinda recall this problem now. I think the conclusion was that I had do the y-sort myself inside of pipeline script to get the masking as I wanted.

#

Generally it's easier to do this on the CPU side with the material swap idea and other logic like not applying the stencil mask when below the objects.

#

OR, you do 2.5D and have that depth information upfront but you wouldn't be able to use transparent sprites

#

For the partial masking, that's a bit more logic to resolve as you don't want to be applying the mask from bottom up, only drawing it if it's being occluded.

#

And even with y-sort there's not enough information there to resolve the issue for what should be masked

normal elm
#

Unfortunately it's not as easy as I thought. I was wondering if I could initially just get it using some depth test on the pipeline side but it doesn't seem to be possible because we are still way too late

sacred osprey
#

rather what I'm trying to say is y-sort is based on the whole rendering, but with this top-down approach usually you want per-pixel masking when the object is being occluded which is really hard.

#

I've done it CPU side by just toggling a mask on the whole rendering if it passed the test

normal elm
#

I've done it CPU side by just toggling a mask on the whole rendering if it passed the test
so if not, nothing happens this way?

#

at this point I might rather just do as Spine does for outline: do a copy of the mesh renderer then adjust a little bit the Z offset, this way I can make it work without any troubles but it's less general.

Its highlighted, but I need to copy the whole renderer and its done at the same render time of original object using the "double sprite" technique

sacred osprey
#

I would just toggle the mask. If it wasn't being occluded I turned it off and if it was then I toggled it on which prevented the mask from applying if my sprite was next to the occluding sprite but wasn't behind it.... still wasn't a perfect solution.

normal elm
#

yup so it seems that there is no easy techniques to do so. Overriding the shader directly might even be the most efficient, fastest and easiest option

sacred osprey
normal elm
#

I naively initially thought I could just draw pixels visible in the shader but the shader doesn't know about any depth since the ZWrite is off for most 2D sprites/renderers...

So basically, the ordering is only done during the render of the 2D pipeline

#

in my case its just basic highlight so parts behind are not shown, if your case it seems to be feasible since you don't care about depth here, am I wrong? 🤔

#

at least for this very specific case!

#

just to give some notes : even the technique of duplicating the mesh to render the highlight on top of it is not that ideal : just tried but lights are not working so I must also handle them in the shader. (which is kinda... logic)

While overriding the original shader to add 2 lines for brightness makes everything work perfectly... 🤔

But I'm not fan of this solution because it's not that generic though it's very efficient

sacred osprey
#

Yeah, I'm not too sure why y-sort wouldn't apply when doing a material override like that. Like I said I think you may have to gather that information yourself if it's not being applied with the pipeline script alone.

#

Yeah, maybe that's the idea. You draw all the geometry through the pipeline scripting instead of just the single material override.