Android - HeightMap Android - HeightMap

ANDROID - HeightMap Implementation.


During, team project - Development for Android ecosystem was studied, Simple apps and later a rendering engine for Android using OpenGL ES 2.0 was developed, which was used in the RollingWave Android version. As a side effect of the same, a mesh loader was molded to be used in the this render engine and using thing a HeightMap was loaded and used in an app. And using the glsl shaders - differnted colours were gibased on the height of the HeightMap.

Graphics :

  • OpenGL ES 2.0 Render Engine.
  • Mesh Loader - HeightMap.
  • Shader Programming.

Description :


Render Engine:

The main aspect of the rendering engine was to handling of Android lifecycle events and its interaction between Java and native code. There are two basic parts to the Java/native JNI code interaction. Most of this interaction is handled by the Android support API, NativeActivity, which is in turm wrapped away from the application by NVIDIA’s version of the Google sample framework nv_native_app_glue It takes care of the event handling and all he life cycle events down to the native code of the app’s process.

    NvEGLUtil* egl = NvEGLUtil::create();
    if (!egl) 
    {
        // if we have a basic EGL failure, we need to exit immediately; nothing else we can do
        nv_app_force_quit_no_cleanup(app);
        return;
    }

	if(!egl)
	{
		LOGD("EGL context not bound.");
	}

    Engine* engine = new Engine(*egl, app);

	long lastTime = egl->getSystemTime();

                        

HeightMap :

I make use of the HeightMap class. As a heightmap is just a bunch of nodes (based on perlin noise) with textures and indices. And which is read in from a RAW file.

    NvFile *file = NvFOpen(filename);
	if(!file) {
		LOGD("HeightMap.cpp - Unable to open file.");
		return;
	}

	//Size of the file.
	size_t size = NvFSize(file);

	numVertices = RAW_WIDTH*RAW_HEIGHT;
	numIndices = (RAW_WIDTH-1)*(RAW_HEIGHT-1)*6;
	vertices = new Vector3[numVertices];
	textureCoords = new Vector2[numVertices];
	indices = new GLuint[numIndices];

	unsigned char* data = new unsigned char[numVertices];
	NvFRead(data, numVertices*sizeof(unsigned char), size, file);
	NvFClose(file);
                        

As textured loading was not possible - I used to the mix function provided in GLSL in order to blend/mix in different colours in the HeightMap shader (heightMap.frag)

precision highp float;
uniform sampler2D diffuseTex;

varying lowp vec2 texCoordOUT;
varying lowp vec3 normalOUT;

varying vec3 worldPosOUT;

void main ( void ) {
	lowp vec4 outputColor = vec4(1,0,0,1);
	if(worldPosOUT.y >= 180.0){
		outputColor = vec4(1,1,1,1);
	} else if(worldPosOUT.y < 180.0 && worldPosOUT.y > 110.0){
		float alpha = (worldPosOUT.y-110.0)/70.0;
		outputColor = mix(vec4(1,1,1,1),vec4(0,1,0,1),1.0-alpha);
	}else if(worldPosOUT.y <= 110.0 && worldPosOUT.y > 70.0){
		outputColor = vec4(0,1,0,1);
	}else if (worldPosOUT.y <=70.0 && worldPosOUT.y > 30.0){
		float alpha = (worldPosOUT.y-30.0)/40.0;
		outputColor = mix( vec4(0,1,0,1),vec4(0.93,0.788,0.686,1),1.0-alpha);
	} else {
		outputColor = vec4(0.93,0.788,0.686,1);
	}

	vec3 cameraPos = vec3(0,500,0);
	vec4 lightColour = vec4(1,1,1,1);
	vec3 lightPos = vec3(2000,500,-1500);
	float lightRadius = 4000.0;

	vec3 incident	= normalize(lightPos - worldPosOUT);
	float lambert 	= max(0.0, dot(incident, normalOUT));

	float dist 		= length(lightPos - worldPosOUT);
	float atten 	= 1.0 - clamp(dist / lightRadius, 0.0, 1.0);

	vec3 viewDir 	= normalize(cameraPos - worldPosOUT);
	vec3 halfDir	= normalize(incident + viewDir);

	float rFactor	= max(0.0, dot(halfDir, normalOUT));
	float sFactor	= pow(rFactor, 50.0);

	vec3 colour 	=   (outputColor.rgb * lightColour.rgb);
	colour 			+= (lightColour.rgb *sFactor) * 0.33;
	outputColor 	= vec4(colour * atten * lambert, 1);
	outputColor.rgb 	+= (outputColor.rgb * lightColour.rgb) * 0.1;	

	gl_FragColor = outputColor;

}