Open KiSetsuFu-PuLiN opened 3 months ago
Does this happen with 4.3? They've improved depth buffer accuracy I think.
The shader turns on depth writing
Writing to ALPHA
always disables depth writing, even if you're writing a 1.0
constant to it. Transparent materials can't write to the depth buffer, otherwise rendering would be broken (you'd see pure black with the depth prepass enabled).
As the class reference says (emphasis mine):
Objects will write to depth during the opaque and the transparent passes. Transparent objects that are close to the camera may obscure other transparent objects behind them.
Note: This does not influence whether transparent objects are included in the depth prepass or not. For that, see Transparency.
The shader turns on depth writing
Writing to
ALPHA
always disables depth writing, even if you're writing a1.0
constant to it. Transparent materials can't write to the depth buffer, otherwise rendering would be broken (you'd see pure black with the depth prepass enabled).As the class reference says (emphasis mine):
Objects will write to depth during the opaque and the transparent passes. Transparent objects that are close to the camera may obscure other transparent objects behind them. Note: This does not influence whether transparent objects are included in the depth prepass or not. For that, see Transparency.
Transparent objects with the depth write set to always will write to the depth buffer during the transparent pass. This doesn't have an impact on the depth prepass, opaque objects, or post process effects, but it does impact the rendering of other transparent objects.
The OPs issue is more likely coming from an assumption that next_pass materials always result in a draw pass after the original pass. I suspect this issue is a duplicate of https://github.com/godotengine/godot/issues/82005 and https://github.com/godotengine/godot/issues/83774
Writing to
ALPHA
always disables depth writing, even if you're writing a 1.0 constant to it. Transparent materials can't write to the depth buffer, otherwise rendering would be broken (you'd see pure black with the depth prepass enabled).
When I tried to stop writing to ALPHA, the two shading had the correct occlusion relationship and everything works as expected.
But when I wrote ALPHA and set depth_draw_always, the result of the first shading did correctly occlude the result of the second shading at certain camera angles, which is very different from the performance when depth_draw_always is not set. This shows that depth writing and depth testing are indeed turned on at this time. The only weird thing is that at certain camera angles, the occlusion relationship is incorrect.
The OPs issue is more likely coming from an assumption that next_pass materials always result in a draw pass after the original pass. I suspect this issue is a duplicate of https://github.com/godotengine/godot/issues/82005 and https://github.com/godotengine/godot/issues/83774
I did assume that the NextPass was rendered after this material, and when I dropped that assumption and used RenderPriority to control the rendering order, the depth test worked fine.
The naming and documentation of NextPass may be misleading.
Material next_pass
Sets the Material to be used for the next pass. This renders the object again using a different material.
Note: next_pass materials are not necessarily drawn immediately after the source Material. Draw order is determined by material properties, render_priority, and distance to camera.
Note: This only applies to StandardMaterial3Ds and ShaderMaterials with type "Spatial".
When the material used in the two shading is the same shader, the RenderPriority is the same, and the position of the vertices relative to the camera is roughly the same, the NextPass material is shaded earlier at some camera angles, instead of being shaded again after the first rendering.
I also found that the documentation's description of RenderPriority
didn't match my experimental results.
int render_priority
void set_render_priority ( int value )
int get_render_priority ( )
Sets the render priority for objects in 3D scenes. Higher priority objects will be sorted in front of lower priority objects. In other words, all objects with render_priority 1 will render before all objects with render_priority 0).
Note: This only applies to StandardMaterial3Ds and ShaderMaterials with type "Spatial".
Note: This will not impact how transparent objects are sorted relative to opaque objects or how dynamic meshes will be sorted relative to other opaque meshes. This is because all transparent objects are drawn after all opaque objects and all dynamic opaque meshes are drawn before other opaque meshes.
Materials with smaller RenderPriority are rendered earlier.
Tested versions
System information
Windows 10 - Godot v4.2.1.stable.official - Forward+
Issue description
I wrote a shader as follows:
The shader turns on depth writing, and can control the distance from the model to the camera through z, and control the transparency of the shading through alpha.
I shaded a model twice with different materials from the same shader, and set the Z value in the NextPass to be slightly smaller, so that the model is farther away from my screen when shaded the second time. In theory, the second shading will never be displayed because it is blocked by the depth write of the first shading.
However, in this MRP, when the camera is adjusted to certain specific angles (generally when the negative z axis of model is facing the camera), the depth test does not prevent the second shading from being displayed.
This is sometimes good and sometimes bad. In most cases, it will be as described above. In a few cases, restarting Godot will return to normal or the depth test will not work at any camera angle.
Steps to reproduce
Open main.tscn in MRP, and then freely control the editor's camera to rotate around the model to observe.
Minimal reproduction project (MRP)
Non-Overlapping Transprancy.zip