3

The game 3D-scene has many objects (background, asteroids, rockets):

private Background background;
private Asteroid[] asteroids = new Asteroid[NUMBER_ASTEROIDS];
private Rocket[] rockets = new Rocket[NUMBER_ROCKETS];
...
public void onDrawFrame(GL10 glUnused) {
    GLES20.glEnable(GLES20.GL_DEPTH_TEST);
    ...
    background.draw();
    for (Asteroid asteroid: asteroids) asteroid.draw(); // draw all asteroids
    for (Rocket rocket: rockets) rocket.draw(); // draw all rockets
    ...
}

Objects of asteroids and rockets use alpha-blending:

public class IceAsteroid extends Object3D implements Asteroid {
    ...
    GLES20.glEnable(GLES20.GL_BLEND);
    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
    ... // draw an object with a texture
    GLES20.glDisable(GLES20.GL_BLEND);
    ...
}

public class Rocket extends Object3D {
    ...
    GLES20.glEnable(GLES20.GL_BLEND);
    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
    ... // draw an object without a texture
    GLES20.glDisable(GLES20.GL_BLEND);
    ...
}

In general, translucency works well for the 3D-scene except that when the rockets are behind the asteroids they (rockets) are not visible. It seems that at this moment the transparency of the asteroids does not work, although the background behind the asteroids is visible. Can anyone please suggest why the rockets are not visible behind the asteroids? Thanks in advance!

Note: I tried to do this:

background.draw();
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
for (Asteroid asteroid: asteroids) asteroid.draw(); // draw all asteroids
for (Rocket rocket: rockets) rocket.draw(); // draw all rockets
GLES20.glDisable(GLES20.GL_BLEND);

But this did not solve the problem.

Solution: On the Rabbid76 advice, I sorted all the translucent objects in order from the back to the front:

Comparator<Object3D> comparatorByZ = (objectA, objectB) -> {
    Float z1 = objectA.getZ();
    Float z2 = objectB.getZ();
    return z1.compareTo(z2);
};
...
background.draw();
Collections.sort(transparentObjects, comparatorByZ);
for (Object3D object3D: transparentObjects) object3D.draw();

In my case, that was enough.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
alexrnov
  • 2,346
  • 3
  • 18
  • 34
  • 1
    Do you disable the [depth test](https://www.khronos.org/opengl/wiki/Depth_Test)? – Rabbid76 May 19 '20 at 11:53
  • @Rabbid76 Thank You for Your attention to the problem! The depth test turn on the beginning of the method onDrawFrame(). (added to the question). – alexrnov May 19 '20 at 12:13
  • @Rabbid76 Sorry for the importunity, but if you disable the depth test: GLES20.glDisable(GLES20.GL_DEPTH_TEST) then the rockets will always displayed in front of the asteroids. Or do need to enable/disable it in another place? – alexrnov May 20 '20 at 02:57

1 Answers1

2

You cannot have both, Blending and the benefits of the Depth Test. You have to do draw the scene in 2 passes. First draw the opaque objects with depth test on and blending off, then draw the transparent objects with depth test on but no writing to the depth buffer, and blending on, in sorted order from the back to the front. See Transparency Sorting.

  1. enable depth test and disable blending
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthMask(GLES20.GL_TRUE);
GLES20.glDisable(GLES20.GL_BLEND);
  1. draw opaque objects

  2. enable depth test, disable writing to the depth buffer and enable blending

GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthMask(GLES20.GL_FALSE);
GLES20.glEnable(GLES20.GL_BLEND);
  1. draw transparent objects in sorted order from the back to the front.

If the transparent objects are not sorted, then the transparent objects will still be arranged correctly, in compare to the opaque objects, but the transparent object itself may not be arranged correctly. When you use blending, then the order matters. The blending function is not commutative, the result is different if the order of covering transparent objects is changed.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174