godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.5k stars 20.26k forks source link

Vulkan: Sprite3D Billboard doesn't work with ORMMaterial3D #58618

Open Verthae opened 2 years ago

Verthae commented 2 years ago

Godot version

4.0 alpha 3 build

System information

Windows 10

Issue description

Sprite3D with Billboard turned on works fine so long as you don't apply an ORMMaterial3D in the Material Override slot image

For whatever reason, the quad that the Sprite3D should display on becomes filed instead of hidden when the material override is applied. I assume the material is making it visible as when you apply a texture to the albedo, you can see the texture on the quad, and the filtering (which is the purpose of applying the material) isn't applying to the billboarded image

image

Steps to reproduce

1) Make a new project with a new Scene using a Sprite3D 2) put the icon.png into the Texture slot of the Sprite3D 3) in Flags set Billboard to Enabled -- the Sprite3D should billboard just fine here -- 4) in Geometry set Material Override to a new ORMMaterial3D --the Quad that the Sprite3D should originally be produced on becomes visible --

Minimal reproduction project

Sprite3D_bug.zip

Calinou commented 2 years ago

Does this occur with StandardMaterial3D?

Verthae commented 2 years ago

Seems like this is happening to any shader used in Material Overlay image Using StandardMaterial3D and a coded ShaderMaterial are all apparently making the quad visible when the Sprite3D has BillBoard enabled.

EDIT: Ah... I'm just realizing - the shader itself has a BillBoard setting, which seems to only 'partially' override the Sprite3D's BillBoard setting, but this just winds up putting the Shader billboard behind the Sprite3D billboard.

image (note how the filter is nearest, but the texture is still linear - because it's displaying from the Sprite3D Billboard

I think my earlier experimentation with this got backtracked, because I was using one of these settings to apply the Sampling setting to a Sprite3D in order to resolve the 'Texture Sampling is per Shader in 3D' which is more difficult to resolve with Sprite3D lacking this setting - though I don't think I had been testing it with the billboard setting in the Sprite3D vs on the Shader. I was going to Material Overlay because something wasn't working with Material Override previously.

Using Material Override seems to eliminate the Sprite3D BillBoard and display as expected image (I don't know how to code in the billboard setting on a ShaderMaterial shown here)

Calinou commented 2 years ago

cc @fbcosentino who implemented the material overlay property in https://github.com/godotengine/godot/pull/53069.

fbcosentino commented 2 years ago

Same issue is happening on 3.5 (where material overlay was originally developed). The code follows the same logic of material override but not skipping the previous materials. Material override also ignores Sprite3D's billboard flag.

I suppose solution for that would be to have both material override and material overlay to read the Sprite3D's billboard feature and override this into their own flags, but I don't really know how to implement that as the hierarchy is reversed (materials are added to the rendering pipeline, not nodes).

Another issue I noted is when setting the billboard flag in the overlay material (which would be the "correct" workaround) the overlay material is rendering behind the base one. Not sure but I believe this is what you described in your last message?

I haven't touched Sprite3D's code yet but it seems to have its own "buffer" hidden material, internally. It doesn't use the geometry logic, and injects the material in the servers directly.

The main problem here I think is making a design decision, rather than implementation. If Sprite3D's billboard property is forced upon the materials, this will probably be very confusing as material properties will be silently "ignored" and "clicking things won't work", and the rendering pipeline will start to become a logic spaghetti ("do things this way, unless you have that combination, in which case you do that instead, but if you have that flag, then go the other way around, but if then..." etc).

If using the geometry's material overlay property, that means you want to have fine control over the materials of the sprite, instead of just using the built-in base material. In that case, you can set the override material as well, since you're already an edge case. Personally, I don't like this. I prefer when there are enough ifs in the code to properly handle any combination I click, but I believe this one might be a case of "but at what cost?".

I'm just a minor contributor who wrote 3 lines, so I'll leave the decision for the top cats. Just leaving for the record my opinion that avoiding the inconvenience of having to set the full pair override+overlay might not be worth the logic awkwardness in the pipeline.