Hello to everyone,

Im fighting with OpenGLES, with shaders and matrix. I need to display triangles and shade them according to a directional light.

My code is the following.

Code :
public void OnDrawFrame (Javax.Microedition.Khronos.Opengles.IGL10 gl)
{
	gl.GlClear((int)GL10.GlColorBufferBit | GL10.GlDepthBufferBit);
 
	// Draw the heightmap.
	// Translate the heightmap into the screen.
	Matrix.SetIdentityM(mModelMatrix, 0);
	Matrix.TranslateM(mModelMatrix, 0, 0.0f, 0.0f, iZoomLevel);
 
	// scaling
	Matrix.SetIdentityM(mScaleMatrix, 0);
	Matrix.ScaleM(mScaleMatrix, 0, scaleX, scaleY, scaleZ);
 
	// Set a matrix that contains the current rotation.
	Matrix.SetIdentityM(mCurrentRotation, 0);
	Matrix.RotateM(mCurrentRotation, 0, mAngleX, 0.0f, 1.0f, 0.0f);
	Matrix.RotateM(mCurrentRotation, 0, mAngleY, 1.0f, 0.0f, 0.0f);
	mAngleX = 0.0f;
	mAngleY = 0.0f;
 
	// Multiply the current rotation by the accumulated rotation, and then
	// set the accumulated rotation to the result.
	Matrix.MultiplyMM(mTemporaryMatrix, 0, mCurrentRotation, 0, mAccumulatedRotation, 0);
	System.Array.Copy(mTemporaryMatrix, 0, mAccumulatedRotation, 0, 16);
 
	Matrix.MultiplyMM(mTemporaryMatrix, 0, mScaleMatrix, 0, mAccumulatedRotation, 0);
	System.Array.Copy(mTemporaryMatrix, 0, mScaleMatrix, 0, 16);
 
	// Rotate the cube taking the overall rotation into account.
	Matrix.MultiplyMM(mTemporaryMatrix, 0, mModelMatrix, 0, mScaleMatrix, 0); //mAccumulatedRotation, 0);
	System.Array.Copy(mTemporaryMatrix, 0, mModelMatrix, 0, 16);
 
	// This multiplies the view matrix by the model matrix, and stores
	// the result in the MVP matrix
	// (which currently contains model * view).
	Matrix.MultiplyMM(mMVPMatrix, 0, mVMatrix, 0, mModelMatrix, 0);
 
	Matrix.MultiplyMV(lightDirInEyeSpace, 0, mTemporaryMatrix, 0, lightDirInModelSpace, 0);
 
	// This multiplies the modelview matrix by the projection matrix,
	// and stores the result in the MVP matrix
	// (which now contains model * view * projection).
	Matrix.MultiplyMM(mTemporaryMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
	System.Array.Copy(mTemporaryMatrix, 0, mMVPMatrix, 0, 16);
 
	mTriangle1.Draw (mMVPMatrix, mVMatrix, lightDirInEyeSpace);
	mTriangle2.Draw (mMVPMatrix, mVMatrix, lightDirInEyeSpace);
}
 
public void OnSurfaceCreated (Javax.Microedition.Khronos.Opengles.IGL10 gl, Javax.Microedition.Khronos.Egl.EGLConfig config)
{
	// Set the background clear color to black.
	GLES20.GlClearColor(1.0f, 1.0f, 1.0f, 0.0f);
 
	// Enable depth testing
	GLES20.GlEnable(GLES20.GlDepthTest);
 
	// Position the eye in front of the origin.
	float eyeX = 0.0f;
	float eyeY = 0.0f;
	float eyeZ = -0.5f;
 
	// We are looking toward the distance
	float lookX = 0.0f;
	float lookY = 0.0f;
	float lookZ = -5.0f;
 
	// Set our up vector. This is where our head would be pointing were we
	// holding the camera.
	float upX = 0.0f;
	float upY = 1.0f;
	float upZ = 0.0f;
 
	// Set the view matrix. This matrix can be said to represent the camera
	// position.
	// NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination
	// of a model and view matrix. In OpenGL 2, we can keep track of these
	// matrices separately if we choose.
	Matrix.SetLookAtM(mVMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
 
	// Initialize the accumulated rotation matrix
	Matrix.SetIdentityM(mAccumulatedRotation, 0);
 
	mTriangle1 = new Triangle ();
	mTriangle1.SetVerts(0f,0f,0, 0.5f,0.0f,0, 0.0f,0.5f,0);
	mTriangle2 = new Triangle ();
	mTriangle2.SetVerts(0f,0f,0, 0.0f, 0.5f,0.0f, 0f,0.0f,0.5f);
}

My triangle class:

Code :
class Triangle
{
	private FloatBuffer vertexBuffer;
	private int mProgram;
	private int mPositionHandle;
	private int mColorHandle;
	private int mMVPMatrixHandle;
	private int mMVMatrixHandle;
	private int mLightDirHandle;
	private int mNormalHandle;
 
	// number of coordinates per vertex in this array
	static int COORDS_PER_VERTEX = 3;
	float[] triangleCoords = new float [] { // in counterclockwise order:
		-0.5f,  -0.5f, 0.0f,   // top
		0.5f, -0.5f, 0.0f,   // bottom left
		0.0f, 0.5f, 0.0f    // bottom right
	};
	private int vertexCount = 3; //triangleCoords.Length / COORDS_PER_VERTEX;
	private int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
 
	// Set color with red, green, blue and alpha (opacity) values
	float[] color = new float[] { 
		0.63671875f, 
		0.76953125f, 
		0.22265625f, 
		1.0f };
 
	public Triangle ()
	{
		// initialize vertex byte buffer for shape coordinates
		// (number of coordinate values * 4 bytes per float)
		ByteBuffer bb = ByteBuffer.AllocateDirect (	triangleCoords.Length * 4);
		// use the device hardware's native byte order
		bb.Order (ByteOrder.NativeOrder ());
 
		// create a floating point buffer from the ByteBuffer
		vertexBuffer = bb.AsFloatBuffer ();
		// add the coordinates to the FloatBuffer
		vertexBuffer.Put (triangleCoords);
		// set the buffer to read the first coordinate
		vertexBuffer.Position (0);
 
		// prepare shaders and OpenGL program
		int vertexShader = MyGLRenderer.LoadShader (GLES20.GlVertexShader,
			vertexShaderCode);
		int fragmentShader = MyGLRenderer.LoadShader (GLES20.GlFragmentShader,
			fragmentShaderCode);
 
		mProgram = GLES20.GlCreateProgram ();             // create empty OpenGL Program
		GLES20.GlAttachShader (mProgram, vertexShader);   // add the vertex shader to program
		GLES20.GlAttachShader (mProgram, fragmentShader); // add the fragment shader to program
		GLES20.GlLinkProgram (mProgram);                  // create OpenGL program executables
	}
 
	public void SetVerts(float v0, float v1, float v2, float v3, float v4, float v5,
		float v6, float v7, float v8)
	{
		triangleCoords[0] = v0;
		triangleCoords[1] = v1;
		triangleCoords[2] = v2;
		triangleCoords[3] = v3;
		triangleCoords[4] = v4;
		triangleCoords[5] = v5;
		triangleCoords[6] = v6;
		triangleCoords[7] = v7;
		triangleCoords[8] = v8;
 
		vertexBuffer.Put(triangleCoords);
		// set the buffer to read the first coordinate
		vertexBuffer.Position(0);
	}
 
	public void Draw (float[] mvpMatrix, float[] mvMatrix, float[] lightDirInEyeSpace)
	{
		// Add program to OpenGL environment
		GLES20.GlUseProgram (mProgram);
 
		// get handle to vertex shader's vPosition member
		mPositionHandle = GLES20.GlGetAttribLocation (mProgram, "vPosition");
 
		// Enable a handle to the triangle vertices
		GLES20.GlEnableVertexAttribArray (mPositionHandle);
		// Prepare the triangle coordinate data
		GLES20.GlVertexAttribPointer (mPositionHandle, COORDS_PER_VERTEX,
			GLES20.GlFloat, false,
			vertexStride, vertexBuffer);
 
		// get handle to shape's transformation matrix
		mMVPMatrixHandle = GLES20.GlGetUniformLocation (mProgram, "uMVPMatrix");
		MyGLRenderer.CheckGlError ("glGetUniformLocation");
		// Apply the projection and view transformation
		GLES20.GlUniformMatrix4fv (mMVPMatrixHandle, 1, false, mvpMatrix, 0);
		MyGLRenderer.CheckGlError ("glUniformMatrix4fv");
 
		//-
 
		mMVMatrixHandle = GLES20.GlGetUniformLocation (mProgram, "u_MVMatrix");
		MyGLRenderer.CheckGlError ("glGetUniformLocation");
		// Apply the projection and view transformation
		GLES20.GlUniformMatrix4fv(mMVMatrixHandle, 1, false, mvMatrix, 0);
		MyGLRenderer.CheckGlError ("glUniformMatrix4fv");
 
		// get handle to shape's transformation matrix
		mLightDirHandle = GLES20.GlGetUniformLocation (mProgram, "u_LightDir");
		MyGLRenderer.CheckGlError ("glGetUniformLocation");
 
		// Apply the projection and view transformation
		GLES20.GlUniform3f(mLightDirHandle, lightDirInEyeSpace[0], lightDirInEyeSpace[1], lightDirInEyeSpace[2] );
		MyGLRenderer.CheckGlError ("GlUniform4f");
 
		// get handle to normal
		mNormalHandle = GLES20.GlGetUniformLocation (mProgram, "a_Normal");
		MyGLRenderer.CheckGlError ("glGetUniformLocation");
 
		// calc normal
		float x = (triangleCoords[4] - triangleCoords[1]) * (triangleCoords[8] - triangleCoords[2]) - (triangleCoords[5] - triangleCoords[2]) * (triangleCoords[7] - triangleCoords[1]);
		float y = (triangleCoords[5] - triangleCoords[2]) * (triangleCoords[6] - triangleCoords[0]) - (triangleCoords[3] - triangleCoords[0]) * (triangleCoords[8] - triangleCoords[2]);
		float z = (triangleCoords[3] - triangleCoords[0]) * (triangleCoords[7] - triangleCoords[1]) - (triangleCoords[4] - triangleCoords[1]) * (triangleCoords[6] - triangleCoords[0]);
 
		// Apply the projection and view transformation
		GLES20.GlUniform3f(mNormalHandle, x, y, z );
		MyGLRenderer.CheckGlError ("GlUniform3f");
 
		//-
 
		// Draw the triangle
		GLES20.GlDrawArrays(GLES20.GlTriangles, 0, vertexCount);
		//GLES20.GlDrawElements (GLES20.GlTriangles, drawOrder.Length,
		//	GLES20.GlUnsignedShort, drawListBuffer);
 
		// Disable vertex array
		GLES20.GlDisableVertexAttribArray (mPositionHandle);
	}

My shaders are:

Code :
uniform mat4 uMVPMatrix;
uniform mat4 u_MVMatrix;
uniform vec3 u_LightDir;
 
attribute vec4 vPosition;
uniform vec4 a_Color; 
uniform vec3 a_Normal;
 
varying vec3 v_Color;
vec3 materialColor; 
 
void main()                    
{                              
    materialColor = vec3(1,0,0);
    vec4 newNormal = u_MVMatrix * vec4(a_Normal, 0.0); 
    float lightIntensity = max(0.0, dot(newNormal.xyz, u_LightDir));
    v_Color = materialColor * lightIntensity; 
 
    gl_Position = uMVPMatrix * vPosition;
}
 
 
precision mediump float; 
 
varying vec3 v_Color;          
 
void main()                    
{                              
   gl_FragColor = vec4(v_Color, 1.0); 
   gl_FragColor = v_Color; 
};

Triangles are not displayed with the right shading.

Could you help me ? Thank you in advance.

Keven Corazza