glDepthFunc and GL_LEQUAL for background drawing in an OpenGL ES 2 Android\iOS game.

For the (semi secret)game I am currently working on(http://www.PompiPompi.net/) I had to implement the background or backdrop of the 3D world.

A simple method to draw the background is having a textured sphere mesh surround the camera.

The issue with this method is that the sphere is not perfect so there are distortions and it doesn’t completely fit the viewing frustum. Which means some geometry that is inside our frustum will be occluded by the sphere.

A different method is to draw a screen space quad at the exact back end of the frustum. This quad will have coordinates in screen space and won’t require transformation.

The back of the plane in screen space coordinates is 1.

You could disable writing into the ZBuffer with glDepthMask(false) and draw the background first. All the geometry that renders afterwards will overwrite the background.

However, what if we want to draw the background last and save on fill rate by using the ZBuffer?

Just drawing the background last should have done that but instead it might not render at all.

We usually clear the depth buffer part of the render buffer into 1.0 which is the highest value for the depth buffer. But our background screen mesh is also rendered into 1!

It turns out the default depth test function in OpenGLES is GL_LESS. Since the ZBuffer is already 1.0 our background screen mesh won’t render.

What we can do is before rendering the screen mesh, we can set the depth test function  into less or equal by calling: glDepthFunc(GL_LEQUAL);

This way our background buffer will not draw at pixels that we have drawn geometry before but will draw on the rest of the “blank” pixels.

Calling a multiple parameters Java method with JNI (Loading ETC1 for Android)

Calling a Java method from C++ with JNI is kind of difficult since you don’t have static type compilation errors.

I was calling a Java method from my Android OpenGL graphics module in order to load an ETC1 texture with this command:

jmethodID mid = env->GetMethodID(cls, "LoadETC1", "(Ljava/lang/String; [I [I)I");

The Java method I was trying to call was the following:

		public int LoadETC1(String s, int[] w1, int[] h1)
		{
			if (!ETC1Util.isETC1Supported())
				return 0;
			try {
				InputStream s2 = assetManager.open(s);
				ETC1Util.ETC1Texture t = ETC1Util.createTexture(s2);
				int textureName = -1;
				int[] texture = new int[1];
				GLES20.glGenTextures(1, texture, 0);
				textureName = texture[0];

		        GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, textureName );

//				GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

		        int w = t.getWidth();
		        int h = t.getHeight();
		        int l = t.getData().capacity();
		        GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 0, ETC1.ETC1_RGB8_OES, t.getWidth(), t.getHeight(), 0, t.getData().capacity(), t.getData());
//		        GLES20.glTexImage2D ( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, w, h, 0,
//		                              GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, ib );

		        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR );
		        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR );
		        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT );
		        GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT );
		        TextureNode n = new TextureNode();
		        w1[0] = t.getWidth();
		        h1[0] = t.getHeight();
		        return texture[0];
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return 0;
		}

The issue was that  GetMethodID was returning 0. In LogCat it mentioned that my method signature is bogus “(Ljava/lang/String; [I [I)I“.

The issue actually was that I had spaces between the 3 parameters of the method. There should be no spaces and there should be ‘;’ only after a non primitive Java class like “Ljava/lang/String;”.

The following method gave a valid jmethodID:

jmethodID mid = env->GetMethodID(cls, "LoadETC1", "(Ljava/lang/String;[I[I)I");