Hello everyone!
Before I’m gonna describe my problem I would like to say that I’ve been trying Defold engine for a couple of months already and I really enjoy it. Great job Defold Team!
On my journey I’ve got the following problem, which I’ve been trying to resolve for about a week already and failed. Perhaps there is a solution and I overlooked it but browsing the forum didn’t help me find the answer to my problem, so here we go.
I want to make something similar to pong but with a perspective view from one of the players and it always looks towards the opposite player. I want to use exclusively sprites for the balls, and for the players. That’s not my picture, but the idea should look somewhat similar
The whole space is 3D and it has to utilise 3d physics as well. No problems so far and everything sounds achievable without any problem.
The table
This one can be a sprite with a material that has a different predicate that is drawn separately before everything (so it always stays at the background, sort of…)
The Paddles and The Balls
HERE I HAVE THE FOLLOWING ISSUE:
Since the camera is in perspective mode, the depth test is not done by considering Z coordinates, but rather a distance from the camera and that creates some artifacts - specifically, some sprites behind the transparent parts simply don’t get drawn. Here’s an example (not related to Pong but rather created to demonstrate the issue):
The Purple Sprite is in front of the Red Sprite
Oops, a little bit of rotation to the right and it gets wrong
Of course, that’s predictable behaviour, because the pivot of the red sprite got closer to the camera, and therefore put the last in the Z-Sorting, that’s why it got drawn the last and covered the purple sprite. None of the the changes in the render_script
provided good result (because depth test works fine, although it’s not applicable to transparent or semi/transparent objects as I have in the pictures above). Ok-ok, it actually worked sometimes… until I decide to rotate the camera again, and we’re back to the step zero
Then I decided to perform the sorting from my custom material by making some changes to the default sprite material (specifcally the vertex shader in it):
vec4 pos = view_proj * vec4(position.xyz, 1.0);
pos.z = -position.z * 0.01 + 0.5;
var_texcoord0 = texcoord0;
gl_Position = pos;
In these changes I added pos.z = var_depth * 0.01 + 0.5;
, where the screen z-coordinate of the vertex is adjusted according to the original object Z-coordinate value (*0.001 + 0.5 is needed to let all objects between -500 to 500 being presented in the range [0; 1] of the screen space, and therefore being drawn)
Unfortunately, this also works just fine until… I decide to rotate the camera…
Drawing into a DepthBuffer…somehow first and then drawing again but based on the generated DepthBuffer? Not an option! The problem of depth testing for semi-transparent objects is not generally resolved, and I see why: if the object is half transparent then should it write the depth values into the depth buffer?
→ The answer is Yes? Nice, then the objects behind will not be rendered properly since they must be visible to some degree through the front semi-transparent object. You get this:
→ The answer is No? Cool, then the transparent objects will be drawn as they come sorted, and that order may not satisfy the needs. Here’s the outcome:
Why do I actually need to resolve that?
On the pong table will be multiple balls coming back and forth at different positions in 3d. The balls are square textures with a ball image on it but transparent corners (Yeah, sprites, but 3d colliders):
Example:
After all I was surprised that in Defold there is no way to control the way how the predicates are sorted (or do I need to write my own C++ extension? I eat c++ for breakfast so I’m not scared, just wondering ), however the render pipeline is pretty well customisable!
All what I need to be happy is simply have the sprites ordered by Z-axis exclusively, regardless of how my camera is oriented or any other variables and parameters.
OR, maybe the vertex shader can take the full responsibility as I've shown above. That will make the overall process much easier that developing some obscure workaround.
Anyway, I hope there is some reasonable solution for that problem. Cheers!