When layering decals on top of another using transparent parts, decals from under the top one show through when being viewed at certain angles. When the parts are not transparent, it works as expected when up close. However, the problem will manifest when viewed a certain distance away. Even if the top layer is offset away from the wall by 1 stud, the problem persists only when transparent parts are used. When offset using non-transparent parts, the problem does not show.
What I expect to happen is for the rendering to not glitch and for the decals to be rendered in the proper order based on how the parts are layered on each other.
This issue occurs at all times in both Studio and in the live server. I am not sure when this started becoming an issue because I haven’t tried doing this before until recently.
Visuals
In all cases, the image with the fish is on top while the other two are below it and are at equal levels.
Is it normal for the bottom image to bleed through the top image when the top image is offset by 1 stud away from the bottom image? Because that’s happening too. In either case, it shouldn’t be happening so I made a bug report about it. I’m going to wait for an official response from Roblox on this one since it can be duplicated.
I think it’s related to how transparent parts are rendered based on distance to the camera, so the furthest ones are rendered first and the nearest are rendered over those.
I had to read what you wrote three times and look at the images that I posted to understand what you are talking about. I think you might be right. The parts that are closest to the camera are rendered last, even if it’s multiple images. They are being combined in a miss-mash way. That does explain a lot about what is going on. It also explains why the apparent order changes based on viewing angle.
Yeah, it would be great if Decals had a position and size property so that you can have multiple Decals on the same surface, and then use the ZIndex property to control the layering/ordering of them, if I am understanding what you are trying to achieve.
EDIT: I meant I assumed that you used multiple parts in order to position the decals in a way you preferred.
Decals already have a transparency and z-index for multiple decals on the same part/surface. This issue is happening because I have decals on different transparent parts. I have the parts arranged in a particular order which the engine doesn’t seem to follow.
For the ‘Trans’ transparent cases, the zIndex will not solve your problem, but this is due to a more complicated thing in the engine. The key issue a lot of transparent object have, not just in Roblox but in game engines as a whole. Is how do you determine which polygon is ‘in front’ of another.
(Side point: Doing that on a per polygon basis is usually quite expensive and some engines use a per triangle sort to achieve this, which Roblox doesn’t do because that system isn’t perfect under all circumstances and it would eat a lot of performance which isn’t acceptable on low performance devices (e.g. mobile). There is also a technique called Order Independent Transparency, but again it doesn’t work in all cases and requires content to be authored specifically)
So for the transparent objects Roblox’s approach is simple, which works in most cases… it merely takes the object’s pivot/center and projects that onto the camera viewing direction to do a ‘coarse sort’. Which means depending on the view angle either the fish is closest, or the thing immediately behind it.
Now obviously for your case this doesn’t work. But until there is a real structured solution to this problem, this will remain an issue for the near future.
A good work around that Roblox has, and most game engines do to, is to use ‘alpha cutout’ mode where the fully transparent pixels are ‘cutout’ of the image. This is very common for foliage. How to set this up is described here: SurfaceAppearance | Documentation - Roblox Creator Hub
So the issue isn’t isolated to just Roblox, but other games engines as well. The way that I see it, I have three options:
Do what you suggest and use SurfaceAppearance. This can be done, but the images in question come from the toolbox and I have no idea what their alpha maps are like.
Resize and reposition the parts so they don’t overlap. This seems to be the most viable option.
Do nothing and live with it.
I guess I’m going to have to live with it for now and resize/reposition when time allows. There is a few areas that are exhibiting this issue.
I have a couple of ideas that might work, but since I don’t have the source code to the engine, I can’t do it myself.
Basically, you raycast from the front surface out in 1 stud increments over the entire front surface of the object. There would be a flag on the object to indicate to do this. Then there would be a maximum distance to raycast to. A good number would be something like 5 studs, but this can be configured as well. That would create a bitmap of which polygons are behind others. This would be done when the engine starts up to reduce the load while playing the game. So when the camera viewing angle changes, the top ploygon would have all 1’s in it’s bitmap. The ones behind it would have 0’s in the overlap areas. The issue with this is that it would work only when the polygons are right on top of each other, because any further apart and the map won’t be as accurate.
This is more CPU intensive, but it works better, and can probably be scaled with graphics quality settings. If transparent parts with decals are within the camera’s field of view, perform a raycast against the transparent parts in a grid of 1x1 studs. So for a 10x10 part that’s facing the camera, that’s 100 points. But for a low graphics setting, it would be a 2x2 grid for 25 points. Upon intersection with a transparent part, make a note of it and keep going until either a non-transparent part is hit or the render distance is hit (also determined by graphics quality settings). That would guarantee correct rendering order.
In any case, thank you for your time in writing a response to explain what’s going on. Now I, and anyone else who encounters this issue, knows what’s going on. It’s not the answer that I was looking for, but it’s an answer.
It is unclear to me what you would do with the information that you acquired in either approach 1 or 2 in order to solve your problem? Yes you would know which one is nearest, but I don’t think you have actionable information to deal with it?
Or maybe they were suggestions for how Roblox rendering could deal with the issue to make it work out of the box? If so, for your particular case a Binary Space Partitioning tree would be an easy and relatively inexpensive thing to do. The downside is that the geometry would need to be static or otherwise moving parts would invalidate the BSP and it would have to be rebuilt. And if we ever exposed transparency ordering overrides this could fix that issue as well as it would fix a lot of problems (this has been pitched internally before, but got shutdown for now due to other issues… mainly relating to putting a lot of complexity on the users of Roblox.)
They are suggestions for Roblox on how to deal with this issues. Yes, the BSP would only work with static data which could be built when the engine starts for performance reasons. But if the part moves, the BSP is freed in memory and the engine reverts to default behavior. However, as I mentioned, there would be a flag that a developer could set in the part’s properties to enable this on a per-part basis, which could also prevent movement (basically lock out CFrame changes) so that would solve that problem as well.
As for exposing the transparency ordering overrides, you could do this and provide documentation with the cavot that Roblox will not respond to support requests. So if a developer uses it, then they are on their own. The downside of that is there is the risk that developers won’t use the API properly, which seems to be an ongoing issue with APIs that are supported.
They are suggestions for Roblox on how to deal with this issues.
Ok, that makes sense. The BSP wouldn’t be terrible if it was done on transparent parts only, it could be fairly dynamic in a way, especially if localized.
I have forwarded your suggestions to our product manager.
No problem. Thanks for considering them. If at all possible, I would like to know what the product manager thinks and if something like this would be implemented.