Hello to everyone,
I’m 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.
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:
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:
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