Hi Mali devs,
I am developing 3D maps Android engine based on OpenGL ES 2.0 + OES_depth_texture plugin and I have strange behavior of one feature on all Mali equipped devices (like Samsung S9-S20, Redmi Note 8Pro etc.).
However, there are no problems on any Adreno equipped devices and on Android Studio Emulator also.
The feature is calculating line of sight visibility around some view point using 5 projections (to the left, right, forward, backward and down) and then draws the result on terrain texture using GLSL shaders.
In normal condition on Adreno devices or Android Studio emulator it looks like this:
But on Mali equipped devices it has strange artifacts near view point (perpendicular lines on each view sector) and it does not see any depth occlusion far from view point.
If I move view point far from the mountain it start ignoring its terrain altitude. You can see on the leftmost picture below there are no black holes on the top as in the image above.
It looks like Mali has wrong/specific data returned by OES_depth_texture plugin in texture or there are problems with precision in fragment shaders calculation?
I have spend already more than a week trying to solve this problem on Mali devices and I need your assistance or advice what may be wrong.
I am defining depth texture like this:
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0 /*level*/, GLES20.GL_DEPTH_COMPONENT, 1024, 1024, 0 /*border*/, GLES20.GL_DEPTH_COMPONENT, GLES20.GL_UNSIGNED_SHORT, null /*pixels*/); GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_TEXTURE_2D, textureName, 0 /*level*/);
Then I use very primitive Vertex and Fragment shaders to read depth texture data and draw green or black color on the terrain based on depth texture values.
Vertex shader:
uniform mat4 mvpMatrix; uniform mat4 slpMatrix[2]; attribute vec4 vertexPoint; varying vec4 sightlinePosition; varying float sightlineDistance; void main() { /* Transform the vertex position by the modelview-projection matrix. */ gl_Position = mvpMatrix * vertexPoint; /* Transform the vertex position by the sightline-projection matrix. */ vec4 sightlineEyePosition = slpMatrix[1] * vertexPoint; sightlinePosition = slpMatrix[0] * sightlineEyePosition; sightlineDistance = length(sightlineEyePosition); }
Fragment shader:
#ifdef GL_FRAGMENT_PRECISION_HIGH precision highp float; #else precision mediump float; #endif uniform float range; uniform vec4 color[2]; uniform sampler2D depthSampler; varying vec4 sightlinePosition; varying float sightlineDistance; const vec3 minusOne = vec3(-1.0, -1.0, -1.0); const vec3 plusOne = vec3(1.0, 1.0, 1.0); void main() { /* Compute a mask that's on when the position is inside the occlusion projection, and off otherwise. Transform the position to clip coordinates, where values between -1.0 and 1.0 are in the frustum. */ vec3 clipCoord = sightlinePosition.xyz / sightlinePosition.w; vec3 clipCoordMask = step(minusOne, clipCoord) * step(clipCoord, plusOne); float clipMask = clipCoordMask.x * clipCoordMask.y * clipCoordMask.z; /* Compute a mask that's on when the position is inside the sightline's range, and off otherwise.*/ float rangeMask = step(sightlineDistance, range); /* Compute a mask that's on when the object's depth is less than the sightline's depth. The depth texture contains the scene's minimum depth at each position, from the sightline's point of view. */ vec3 sightlineCoord = clipCoord * 0.5 + 0.5; float sightlineDepth = texture2D(depthSampler, sightlineCoord.xy).r; float occludeMask = step(sightlineDepth, sightlineCoord.z); /* Modulate the RGBA color with the computed masks to display fragments according to the sightline's configuration. */ gl_FragColor = mix(color[0], color[1], occludeMask) * clipMask * rangeMask; }
Why this approach does not work only on Mali GPUs? It there any precision problem? Could you assist any workaround for Mali GPU?
Thanks.
Glad it helped =)