Fickering issues on some Android devices

All topics about ZGameEditor goes here.

Moderator: Moderators

User avatar
Ats
Posts: 770
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Fickering issues on some Android devices

Post by Ats »

Hello, I just tested Omeganaut on my father's phone, and it's a disaster: there are serious flickering issues between the ground and the mountains, and the same happens on most of the slopes that intersect something else.

It's a Huawei Mate 20 Pro, from 2018. I don't know why it would behave like that, since the game is working nicely on older devices.

So I searched a bit on the internet and I found something similar here: https://community.khronos.org/t/flicker ... oid/104038
They are talking about cleaning the depth buffer:
GLES20.glClearColor(0, 0, 0, 1);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glClearDepthf(1.0f);
...
GLES20.glClear( GL_DEPTH_BUFFER_BIT );
But since this is pure opengl calls, I'm not sure where to add that, and if it would work...
Or maybe it is coming from the shaders? Would you guys have insights on this problem, as I really don't have a clue :|
User avatar
Kjell
Posts: 1915
Joined: Sat Feb 23, 2008 11:15 pm

Re: Fickering issues on some Android devices

Post by Kjell »

Hi Ats,
Ats wrote: Sat Sep 10, 2022 5:03 pmSo I searched a bit on the internet and I found something similar here: https://community.khronos.org/t/flicker ... oid/104038
They are talking about cleaning the depth buffer:
GLES20.glClearColor(0, 0, 0, 1);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glClearDepthf(1.0f);
...
GLES20.glClear( GL_DEPTH_BUFFER_BIT );
But since this is pure opengl calls, I'm not sure where to add that, and if it would work...
As long as App.ClearScreenMode is set to ClearScreen the depth buffer already gets cleared each frame automatically ( you can see this here ). Are you using any RenderTargets or something? Or are you using any Materials with alpha values that aren't set to 1?
Ats wrote: Sat Sep 10, 2022 5:03 pmOr maybe it is coming from the shaders? Would you guys have insights on this problem, as I really don't have a clue :|
Hard to tell without seeing any footage .. would it be possible to make a off-screen recording using another phone or camera?

K
User avatar
Ats
Posts: 770
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: Fickering issues on some Android devices

Post by Ats »

  • App.ClearScreenMode is set to ClearScreen
  • I don't use RenderTarget in the project
  • I set all my Materials alpha manually to 1, because I already had surprises with that on Android. The only transparent materials are the sky and the explosions
Here's the video: https://we.tl/t-ZhsObApW8M

Maybe I could make a strip down example when I'll get back home :wink:
User avatar
Ats
Posts: 770
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: Fickering issues on some Android devices

Post by Ats »

Only the terrain is flickering. It should look like this:
Screenshot_20220911-103515.png
Screenshot_20220911-103515.png (349.91 KiB) Viewed 15200 times
It uses the same material as the other objects, like the trees.
It's RenderOrder is Depthsorted, like the rest.
It has his own Category number.
The only big difference is that it's a generated mesh.
User avatar
VilleK
Site Admin
Posts: 2359
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Re: Fickering issues on some Android devices

Post by VilleK »

I haven't checked the video yet but could it be that the mountain meshes are placed very close to each other, so there are issues with z-buffer precision and the flickering is that mountains "fight" over which one is closest to the camera?

This could happen if this particular device has a depth buffer with low precision.

Kjell can correct me, but I think you can get better range of the zbuffer by adjusting ClipNear and ClipFar so that you reduce the difference between them.
User avatar
Ats
Posts: 770
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: Fickering issues on some Android devices

Post by Ats »

That is exactly what I was reading: https://www.khronos.org/opengl/wiki/Dep ... _Precision
The ClipFar was at 1000, and I don't remember why, since I started that project too long ago.
The fog is between 300 and 500. And objects are created at 600.
I'm going to reduce the ClipFar and see how it goes :wink:
User avatar
Ats
Posts: 770
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: Fickering issues on some Android devices

Post by Ats »

I reduced ClipFar to 500. Then I tried 100 (base) and even 1. It doesn't change a thing, and it's not clipping anything. Increasing ClipNear isn't working either. Are those taken into account when rendering with GLBase ES2/GL3?
User avatar
Kjell
Posts: 1915
Joined: Sat Feb 23, 2008 11:15 pm

Re: Fickering issues on some Android devices

Post by Kjell »

Hi guys,
VilleK wrote: Sun Sep 11, 2022 1:21 pmI think you can get better range of the zbuffer by adjusting ClipNear and ClipFar so that you reduce the difference between them.
Correct, this can alleviate z-fighting problems because you're basically giving the same amount of pixel-depth to a smaller depth-region. However, the glichting that Ats is experiencing ( on that particular Android device ) doesn't appear to be caused by lack of z-buffer precision.
Ats wrote: Sun Sep 11, 2022 3:39 pmI reduced ClipFar to 500. Then I tried 100 (base) and even 1. It doesn't change a thing, and it's not clipping anything. Increasing ClipNear isn't working either. Are those taken into account when rendering with GLBase ES2/GL3?
Yes, ClipNear and ClipFar are taken into account in ES2/GL3 mode. Here's a simple demonstration:

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" GLBase="1" FileVersion="2">
  <OnUpdate>
    <ZExpression>
      <Expression>
<![CDATA[//

float t = cos(App.Time)*5;

App.ClipNear = 10+t;
App.ClipFar = 20+t;]]>
      </Expression>
    </ZExpression>
  </OnUpdate>
  <OnRender>
    <UseMaterial Material="GridMaterial"/>
    <RenderTransformGroup Translate="0 2 0" Rotate="0.25 0 0">
      <Children>
        <RenderMesh Mesh="GridMesh"/>
      </Children>
    </RenderTransformGroup>
    <RenderTransformGroup Translate="0 -2 0" Rotate="0.75 0 0">
      <Children>
        <RenderMesh Mesh="GridMesh"/>
      </Children>
    </RenderTransformGroup>
  </OnRender>
  <Content>
    <Mesh Name="GridMesh">
      <Producers>
        <MeshBox Scale="8 8 1" XCount="7" YCount="7" Grid2DOnly="255"/>
      </Producers>
    </Mesh>
    <Shader Name="GridShader">
      <VertexShaderSource>
<![CDATA[//

uniform mat4 modelViewProjectionMatrix;
attribute vec3 position;

void main()
{
  gl_Position = modelViewProjectionMatrix * vec4(position, 1.0);
}]]>
      </VertexShaderSource>
      <FragmentShaderSource>
<![CDATA[//

void main()
{
  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}]]>
      </FragmentShaderSource>
    </Shader>
    <Material Name="GridMaterial" Shading="2" Light="0" Shader="GridShader"/>
  </Content>
</ZApplication>
K
User avatar
Ats
Posts: 770
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: Fickering issues on some Android devices

Post by Ats »

My bad, I forgot that ClipNear and ClipFar are also present on the Camera options.
So they are working, and I reduced the gap as much as I could.
User avatar
Ats
Posts: 770
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: Fickering issues on some Android devices

Post by Ats »

The flickering problem appears on the terrain, but also on big blocks that constitute the walls, roof and ceiling of the Mothership stage. Those are the only few models that are generated with ZGE, and not imported. But they are also the biggest models in the game.
I believe the flickering comes from one of those two, or maybe the accumulation of both. I'm going to make a strip down test when I'll have some time.
User avatar
VilleK
Site Admin
Posts: 2359
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Re: Fickering issues on some Android devices

Post by VilleK »

Ats wrote: Tue Sep 13, 2022 8:34 am The flickering problem appears on the terrain, but also on big blocks that constitute the walls, roof and ceiling of the Mothership stage. Those are the only few models that are generated with ZGE, and not imported. But they are also the biggest models in the game.
I believe the flickering comes from one of those two, or maybe the accumulation of both. I'm going to make a strip down test when I'll have some time.
Try exporting such a generated model and check in some 3d-modeller if the meshes are malformed in some way. Such as several triangles in same exact position or triangles with zero area.
User avatar
Ats
Posts: 770
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: Fickering issues on some Android devices

Post by Ats »

So today I tried ChatGTP, asking it questions about GLSL shaders. Turns out it was super helpful with advices like:
  • Avoid using uniform arrays if possible. Instead of using a uniform matrix for the light position, light color ambient, and fog color, you could use individual uniform variables for each of these values. This would reduce the number of uniform calls made by the shader and improve performance.
  • Use const variables wherever possible. Declaring variables as const allows the compiler to optimize them better and can improve performance. For example, you could declare the value 3.0 as a const variable at the top of the shader.
  • Avoid using mix() if possible. mix() is a relatively expensive operation and can impact performance, especially on mobile devices. You might consider using a conditional statement or ternary operator instead.
  • Use in and out keywords for varying variables. Using the in and out keywords for varying variables allows the compiler to optimize these variables better and can improve performance.
  • Consider using texture lookups instead of uniform variables for globalColor, LAmbient, and LDiffuse. Textures are generally faster to access than uniform variables, especially on mobile devices.
  • Avoid using dot() if possible. The dot() function can be relatively expensive to compute, especially on mobile devices. You might consider using the length() function or a more efficient alternative instead.
  • Avoid using the [0][0] notation to access the first element of a matrix. Instead, use the [0] notation to access the first column of the matrix. This is generally more efficient and can improve performance.
And most of all, replacing

Code: Select all

#ifdef GL_ES
  precision mediump float;
#endif
by

Code: Select all

#ifdef GL_ES
  precision highp float;
#endif
Solved all my clipping problems on Android. It's the magic of Christmas :lol:

But now I'm wondering if both Vertex and Fragment need to be high precision, or if I could optimize one part only, and if it is worth doing so.
Or maybe I could just get rid of that #ifdef GL_ES test. Then will it be highp? Android devices are pretty strong nowadays.

Edit:
I just tried removing the test, and I'm now flying in a blue void instead of the pretty mountains. No #ifdef GL_ES test removal, then :lol:
User avatar
Kjell
Posts: 1915
Joined: Sat Feb 23, 2008 11:15 pm

Re: Fickering issues on some Android devices

Post by Kjell »

Hi Ats,

ChatGPT is pretty impressive, but it's certainly not perfect ( yet ).
Ats wrote: Sun Dec 25, 2022 12:06 pmAvoid using uniform arrays if possible. Instead of using a uniform matrix for the light position, light color ambient, and fog color, you could use individual uniform variables for each of these values. This would reduce the number of uniform calls made by the shader and improve performance.
Not exactly sure what point it's trying to make here. It starts by saying "avoid uniform arrays" .. which in case the emphasis is on arrays ( plural ) is valid, but then it makes a point about using individual uniform variables instead of a uniform matrix, which is the exact opposite of the "reduce uniform calls" statement it ends with.
Ats wrote: Sun Dec 25, 2022 12:06 pmUse const variables wherever possible. Declaring variables as const allows the compiler to optimize them better and can improve performance. For example, you could declare the value 3.0 as a const variable at the top of the shader.
True, if you use the same value a bunch of times in your source and don't want to keep entering the literal value, you can use a constant. Using a variable for a constant value would be pretty silly.
Ats wrote: Sun Dec 25, 2022 12:06 pmAvoid using mix() if possible. mix() is a relatively expensive operation and can impact performance, especially on mobile devices. You might consider using a conditional statement or ternary operator instead.
This one is a little weird. Mix isn't all that expensive nor can it be avoided in certain situations. But the suggested alternative of conditionals can do way more harm to performance if you're not careful.
Ats wrote: Sun Dec 25, 2022 12:06 pmUse in and out keywords for varying variables. Using the in and out keywords for varying variables allows the compiler to optimize these variables better and can improve performance.
True, but pay attention to which ES version you're targeting.
Ats wrote: Sun Dec 25, 2022 12:06 pmConsider using texture lookups instead of uniform variables for globalColor, LAmbient, and LDiffuse. Textures are generally faster to access than uniform variables, especially on mobile devices.
Generally yes .. but only generally, i've encountered situations where texture lookups in vertex shaders caused tremendeous slowdown in performance.
Ats wrote: Sun Dec 25, 2022 12:06 pmAvoid using dot() if possible. The dot() function can be relatively expensive to compute, especially on mobile devices. You might consider using the length() function or a more efficient alternative instead.
Uhm, what? :-P
Ats wrote: Sun Dec 25, 2022 12:06 pmAvoid using the [0][0] notation to access the first element of a matrix. Instead, use the [0] notation to access the first column of the matrix. This is generally more efficient and can improve performance.
If you're accessing individual vec4 columns of a matrix this is the preferred approach yes.
Ats wrote: Sun Dec 25, 2022 12:06 pmAnd most of all, replacing "precision mediump float;" with "precision highp float;" Solved all my clipping problems on Android.
Hmm, in a lot of situations 16-bit half floats ( which is usually what you get when using mediump ) is plenty.

Image

They give you 10-bit ( 1024 values ) precision whichever range / exponent you're in. You can check out the precision limitations per range here. Perhaps you're using relatively big values in your game?
Ats wrote: Sun Dec 25, 2022 12:06 pmBut now I'm wondering if both Vertex and Fragment need to be high precision, or if I could optimize one part only, and if it is worth doing so.
It all depends on your needs, but generally you won't need high precision in your fragment shaders.
Ats wrote: Sun Dec 25, 2022 12:06 pmOr maybe I could just get rid of that #ifdef GL_ES test. Then will it be highp?
By default the ES values are as follows ( page 42 )

Code: Select all

Vertex Shader
	precision highp float;
	precision highp int;
	precision lowp sampler2D;
	precision lowp samplerCube;

Fragment Shader
	precision mediump int;
	precision lowp sampler2D;
	precision lowp samplerCube;
You can also use precision identifiers for individual function calls if needed.

K
User avatar
Ats
Posts: 770
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: Fickering issues on some Android devices

Post by Ats »

Hahaha thanks ChatKjell for the great explanations :wink:
Perhaps you're using relatively big values in your game?
The drawing distance is 500. And Things appears at a distance of 600 to avoid suddenly poping out of the fog. That's 5x the base drawing distance of ZGE. Maybe the problem comes from that, but I'm not going to divide everything per 5 at this point...
By default the ES values are as follows ( page 42 )
Ok, so float is highp by default then.
But I tried once again, if I suppress

Code: Select all

#ifdef GL_ES
  precision highp float;
#endif
Everything is broken on some Android devices. So I'm just going to keep it like that and continue with making the game :lol:

Thanks for the GLES documentation, I'm going to read that during my next train trip.
User avatar
Kjell
Posts: 1915
Joined: Sat Feb 23, 2008 11:15 pm

Re: Fickering issues on some Android devices

Post by Kjell »

Hi Ats,
Ats wrote: Tue Dec 27, 2022 9:40 amThe drawing distance is 500. And Things appears at a distance of 600 to avoid suddenly poping out of the fog.
In the 256-512 range the smallest interval that can be expressed using a half-float is 0.25. Whether that's a problem or not depends entirely on your situation. Do keep in mind that ( for example ) incoming vertex data will be 32-bit floats regardless, it's only the computations that are done using half-float when you use medium precision.

How are you calculating the screen position of your vertices in your vertex shader? Simply "modelViewProjectionMatrix * vec4(position, 1.0)"? Or are you using multiple matrix multiplications?
Ats wrote: Tue Dec 27, 2022 9:40 amOk, so float is highp by default then.
Only vertex shaders have float set to high precision by default. Fragment shaders don't have a default float precision, so you HAVE to define that yourself if you're making use of floats in your fragment shader.

Anyway, if changing your vertex shader float precision to high solves your problems, than maybe just go with that .. i doubt you'll be cutting off a ton of Android devices ( it's usually fragment shaders on ES that don't support high float precision ).

K
Post Reply