OGL ES 2.0 Orthogonal Matrix result position unexpected - android

I'm having some trouble figuring out, why my triangle is not rendered at the expected position.
I want to draw this triangle:
private float vVertices[] = { 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f};
First I create a Projection Matrix as described here
float aspect_ratio = 800.0f/480.0f;
ortho_matrix(-aspect_ratio, aspect_ratio, -1.0f, 1.0f, -1.0f, 1.0f, PROJECTION_MATRIX);
Then I create a View Matrix and multiply those two:
Matrix.setLookAtM(VIEW_MATRIX, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, PROJECTION_MATRIX, 0, VIEW_MATRIX, 0);
Now I send the mvpMatrix to my Shader,
String vertexShader = "attribute vec4 vPosition; \n" +
"uniform mat4 orthoMatrix;" +
"void main()\n" +
"{\n" +
" gl_Position = vPosition * orthoMatrix;" +
"}";
where the vertices are translated using this matrix.
However, this is not the result I was expecting.
The following image is the result of the above code:
I expected the triangle to have its origin in 0, 0, 0 - so in the center of the screen like this:
From the above code, can anyone tell me what I did wrong, or what I did miss?
edit
Ok, it seems the koordinates are somehow mirrored...
so it looks like this
1 ----+---- -1
When I inverse the aspect_ratio parameters in the ortho_matrix call it looks right. But why is this nessecary?

You're doing the vertex shader multiplication backwards.
It should be :
gl_Position = orthoMatrix * vPosition;

Related

OpenGL ES 2 Color buffer not working

I've recently started using OpenGL ES 2 for android. I followed their examples for drawing shapes, and I went further and created a cube. I'm now trying to achieve a nice color effect(each face a different color). I ve defined a colorBuffer which has a color for each vertex, but when I'm drawing the shape the image is black.
If I use only one color, instead of the buffer the shape is fine.
I tried to adapt my colorBuffer from the positionBuffer, but I'm doing something wrong.
Here is my code:
public class Cube {
private FloatBuffer vertexBuffer; // Buffer for vertex-array
private final FloatBuffer colorsBuffer;
private static final int COORDS_PER_VERTEX = 3;
private static final int COORDS_PER_COLOR = 4;
private ShortBuffer drawListBuffer;
private int mColorHandle;
// float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
private float colors[] ={
// FRONT
1.0f, 0.5f, 0.0f, 1.0f,
1.0f, 0.5f, 0.0f, 1.0f,
1.0f, 0.5f, 0.0f, 1.0f,
1.0f, 0.5f, 0.0f, 1.0f,
//RIGHT
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
//RIGHT
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
//RIGHT
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
//RIGHT
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
//RIGHT
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
};
short[] drawOrder = {
0, 1, 2, 0, 2, 3,
4, 5, 6, 4, 6, 7,
8, 9, 10, 8, 10, 11,
12, 13, 14, 12, 14, 15,
16, 17, 18, 16, 18, 19,
20, 21, 22, 20, 22, 23,
};
private float cubeCoords[] = {
// FRONT
-1.0f, 1.0f, 1.0f, // 0. top-left-front
-1.0f, -1.0f, 1.0f, // 1. bottom-left-front
1.0f, -1.0f, 1.0f, // 2. bottom-right-front
1.0f, 1.0f, 1.0f, // 3. top-right-front
// RIGHT
1.0f, 1.0f, 1.0f, // 3. top-right-front
1.0f, -1.0f, 1.0f, // 2. bottom-right-front
1.0f, -1.0f, -1.0f, // 4. right-top-front
1.0f, 1.0f, -1.0f, // 5. right-top-back
// BACK
1.0f, 1.0f, -1.0f, // 5. right-top-back
1.0f, -1.0f, -1.0f, // 4. right-top-front
-1.0f, -1.0f, -1.0f, // 6. right-top-back
-1.0f, 1.0f, -1.0f, // 7. left-top-back
// LEFT
-1.0f, 1.0f, -1.0f, // 7. left-top-back
-1.0f, -1.0f, -1.0f, // 6. right-top-back
-1.0f, -1.0f, 1.0f, // 1. bottom-left-front
-1.0f, 1.0f, 1.0f, // 0. top-left-front
// BOTTOM
-1.0f, -1.0f, 1.0f, // 1. bottom-left-front
1.0f, -1.0f, 1.0f, // 2. bottom-right-front
1.0f, -1.0f, -1.0f, // 4. right-top-front
-1.0f, -1.0f, -1.0f, // 6. right-top-back
// TOP
-1.0f, 1.0f, 1.0f, // 0. top-left-front
1.0f, 1.0f, 1.0f, // 3. top-right-front
1.0f, 1.0f, -1.0f, // 5. right-top-back
-1.0f, 1.0f, -1.0f, // 7. left-top-back
};
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
private int MVPMatrixHandle;
private int mPositionHandle;
private int colorHandle;
private final int mProgram;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
private final int colorStride = COORDS_PER_COLOR * 4;
private final int vertexCount = cubeCoords.length / COORDS_PER_VERTEX;
// Constructor - Set up the buffers
public Cube() {
Log.d("TAG","vertexCount: "+vertexCount);
// Setup vertex-array buffer. Vertices in float. An float has 4 bytes
ByteBuffer vbb = ByteBuffer.allocateDirect(cubeCoords.length * 4);
vbb.order(ByteOrder.nativeOrder()); // Use native byte order
vertexBuffer = vbb.asFloatBuffer(); // Convert from byte to float
vertexBuffer.put(cubeCoords); // Copy data into buffer
vertexBuffer.position(0); // Rewind
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(
// (# of coordinate values * 2 bytes per short)
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
colorsBuffer = ByteBuffer.allocateDirect(colors.length * 4).order(ByteOrder.nativeOrder())
.asFloatBuffer();
colorsBuffer.put(colors);
colorsBuffer.position(0);
int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glLinkProgram(mProgram);
}
// Draw the shape
public void draw(float[] mvpMatrix) {
GLES20.glUseProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
MVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawing the triangle
// GLES20.glUniform4fv(mColorHandle, 1, color, 0);
GLES20.glEnableVertexAttribArray(mColorHandle);
GLES20.glVertexAttribPointer(mColorHandle, COORDS_PER_COLOR, GLES20.GL_FLOAT, false,
colorStride, colorsBuffer);
GLES20.glUniformMatrix4fv(MVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
You're not doing anything with the color data in your shader programs, so you're uploading the data and not doing anything with it.
You need to add handling code for the new vertex attribute to your shaders; something like this:
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"attribute mediump vec4 vColor;" +
"varying mediump vec4 vaColor;" +
"void main() {" +
" vaColor = vColor;" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"varying mediump vec4 vaColor;" +
"void main() {" +
" gl_FragColor = vaColor;" +
"}";

Using 3d primatives into Particle System

I am starting with this as a basis.
https://github.com/danginsburg/opengles-book-samples/tree/master/Android/Ch13_ParticleSystem
So I have been reading the book that this is based off of and I am struggling to understand how to load another object into the buffer that is not a bitmap. For instance i have created a cube class with normals, vertices, and textures
class Cube
{
public final float VERTICES[] = {
-0.5f, -0.5f, -0.5f, // Back bottom left
0.5f, -0.5f, -0.5f, // Back bottom right
0.5f, 0.5f, -0.5f, // Back top right
-0.5f, 0.5f, -0.5f, // Back top left
-0.5f, -0.5f, 0.5f, // Front bottom left
0.5f, -0.5f, 0.5f, // Front bottom right
0.5f, 0.5f, 0.5f, // Front top right
-0.5f, 0.5f, 0.5f // Front top left
};
final float[] cubeNormalData =
{
// Front face
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
// Right face
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
// Back face
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
// Left face
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
// Top face
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
// Bottom face
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f
};
final float[] cubeTextureCoordinateData =
{
// Front face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Right face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Back face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Left face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Top face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
// Bottom face
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
}
I'm assuming I will need to write a new function to load the cube data, may need help fleshing this out.
private int loadCube() {
Cube cube = new Cube();
float [] cubeData;
float[] cubeVerts = cube.getVERTICES();
float[] cubeNorms = cube.getCubeNormalData();
float[] cubeTexts = cube.getCubeTextureCoordinateData();
for (int i=0; i<NUM_PARTICLES;i++)
{
// add all the parts to the buffer somehow
}
//do some kind og GLES20.glBind
return particleId[0]; // im not sure what this index does just yet but loadTexture has one
}
I think that's what I have to do, though if i missed some important please let me know.
EDIT**********************************************
OK so, I've been making progress and realized that my question was probably too vague. I am currently getting an index out of bounds error, though im sure i am binding the data incorrectly and doing something wrong with the shader. If you could point out what i am doing wrong that would be greatly appreciated
I am loading the data into one buffer of size 32 where:
//[0] is lifetime
//1-3 is end pos
//4-6 is start post
//7-31 is vert data which is added from the cube
So i have these member variables
private FloatBuffer mParticles;
private Context mContext;
private final int NUM_PARTICLES = 10000;
private final int PARTICLE_SIZE = 32; // was 7
private final float[] mParticleData = new float[NUM_PARTICLES * PARTICLE_SIZE];
then i have an onSurfaceCreate Function which i am getting an out of bounds error for when i try to add the verts
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
String vShaderStr =
"uniform float u_time; \n" +
"uniform vec3 u_centerPosition; \n" +
"attribute float a_lifetime; \n" +
"attribute vec3 a_startPosition; \n" +
"attribute vec3 a_endPosition; \n" +
"varying float v_lifetime; \n" +
"void main() \n" +
"{ \n" +
" if ( u_time <= a_lifetime ) \n" +
" { \n" +
" vec3 rotation = vec3(.1*cos(u_time*10),0,.1*cos(u_time*10)); \n" +
" gl_Position.xyz = a_startPosition + rotation + \n" +
" (u_time/10f * a_endPosition); \n" +
" gl_Position.xyz += u_centerPosition; \n" +
" gl_Position.w = 1.0; \n" +
" } \n" +
" else \n" +
" gl_Position = vec4( -1000, -1000, -1000, 0 ); \n" +
" v_lifetime = 1.0 - ( u_time / a_lifetime ); \n" +
" v_lifetime = clamp ( v_lifetime, 0.0, 1.0 ); \n" +
" gl_PointSize = 40.0; \n" +
"}";
String fShaderStr =
"precision mediump float; \n" +
"uniform vec4 u_color; \n" +
"varying float v_lifetime; \n" +
"uniform sampler2D s_texture; \n" +
"void main() \n" +
"{ \n" +
" vec4 texColor; \n" +
" texColor = texture2D( s_texture, gl_PointCoord ); \n" +
" gl_FragColor = vec4( u_color ) * texColor; \n" +
" gl_FragColor.a *= v_lifetime; \n" +
"} \n";
// Load the shaders and get a linked program object
mProgramObject = ESShader.loadProgram(vShaderStr, fShaderStr);
// Get the attribute locations
mLifetimeLoc = GLES20.glGetAttribLocation(mProgramObject, "a_lifetime");
mStartPositionLoc = GLES20.glGetAttribLocation(mProgramObject, "a_startPosition");
mEndPositionLoc = GLES20.glGetAttribLocation(mProgramObject, "a_endPosition");
mVertStartPositionLoc = GLES20.glGetAttribLocation(mProgramObject, "a_vertStartPosition");
// Get the uniform locations
mTimeLoc = GLES20.glGetUniformLocation(mProgramObject, "u_time");
mCenterPositionLoc = GLES20.glGetUniformLocation(mProgramObject, "u_centerPosition");
mColorLoc = GLES20.glGetUniformLocation(mProgramObject, "u_color");
mSamplerLoc = GLES20.glGetUniformLocation(mProgramObject, "s_texture");
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Cube cube = new Cube();
float[] cubeVerts = cube.getVERTICES();
// Fill in particle data array
Random generator = new Random();
for (int i = 0; i < NUM_PARTICLES; i++) { //num particles =31
//[0] is lifetime
//1-3 is end pos
//4-6 is start post
//7-31 is vert data which is added from the cube
// Lifetime of particle
mParticleData[i * PARTICLE_SIZE + 0] = generator.nextFloat() *10f;
// End position of particle
mParticleData[i * PARTICLE_SIZE + 1] = generator.nextFloat() * 2.0f - 1.0f;
mParticleData[i * PARTICLE_SIZE + 2] = generator.nextFloat() * 5.0f +5f;// - 1.0f;
mParticleData[i * PARTICLE_SIZE + 3] = generator.nextFloat() * 2.0f - 1.0f;
// Start position of particle
mParticleData[i * PARTICLE_SIZE + 4] = generator.nextFloat() * 0.25f - 0.125f;
mParticleData[i * PARTICLE_SIZE + 5] = generator.nextFloat() * 0.25f - 0.125f;
mParticleData[i * PARTICLE_SIZE + 6] = generator.nextFloat() * 0.25f - 0.125f;
for(int x=0; x<cubeVerts.length;x++)
{
mParticleData[i *PARTICLE_SIZE + 7 + x] = cubeVerts[x];
}
}
mParticles = ByteBuffer.allocateDirect(mParticleData.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mParticles.put(mParticleData).position(0);
// Initialize time to cause reset on first update
mTime = 10f;
}
And in my onDrawFrame i have this:
public void onDrawFrame(GL10 glUnused) {
update();
// Set the viewport
GLES20.glViewport(0, 0, mWidth, mHeight);
// Clear the color buffer
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Use the program object
GLES20.glUseProgram(mProgramObject);
// Load the vertex attributes
mParticles.position(0);
GLES20.glVertexAttribPointer(mLifetimeLoc, 1, GLES20.GL_FLOAT,
false, PARTICLE_SIZE * 4,
mParticles);
mParticles.position(1);
GLES20.glVertexAttribPointer(mEndPositionLoc, 3, GLES20.GL_FLOAT,
false, PARTICLE_SIZE * 4,
mParticles);
mParticles.position(4);
GLES20.glVertexAttribPointer(mStartPositionLoc, 3, GLES20.GL_FLOAT,
false, PARTICLE_SIZE * 4,
mParticles);
mParticles.position(7);
GLES20.glVertexAttribPointer(mVertStartPositionLoc, 4, GLES20.GL_FLOAT,
false, PARTICLE_SIZE * 4,
mParticles);
GLES20.glEnableVertexAttribArray(mLifetimeLoc);
GLES20.glEnableVertexAttribArray(mEndPositionLoc);
GLES20.glEnableVertexAttribArray(mStartPositionLoc);
GLES20.glEnableVertexAttribArray(mVertStartPositionLoc);
// Blend particles
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE);
// Set the sampler texture unit to 0
GLES20.glUniform1i(mSamplerLoc, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
//GLES20.glDrawArrays(GLES20.GL_POINTS, 0, NUM_PARTICLES);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,NUM_PARTICLES*36);
}

Open gl ES 2 orthographic projection and rotation

my rotation works normally this way :
public void onDrawFrame(GL10 unused) {
float[] scratch = new float[16];
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.setLookAtM(mViewMatrix, 0, 0f ,0f, -3f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
Matrix.setRotateM(mRotationMatrix, 0, i, 0, 0, 1.0f);
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
mTriangle.draw(scratch);
}
with this shader vertex :
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
But when i want to change my 0x;0y coordinate to be at the top left like this :
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = vec4 ( vPosition.x * 2.0 / 1280.0 - 1.0," +
"vPosition.y* - 2.0 / 800.0 + 1.0," +
"vPosition.z, " +
"1.0);" +
"}";*
With these vertices :
static float triangleCoords[] = {
300.0f, 0.0f, 0.0f,
0.0f, 500.0f, 0.0f,
1280.0f, 500.0f, 0.0f
};
Picture : http://i.stack.imgur.com/aRQa9.jpg
My triangle appears like i would like but i can't see my rotation anymore . In order to solve i tried a lot of things like multiply this one by uMVPMatrix ,but now i can see the rotation but i always get coordinate problems as it appears at the middle of the screen, and my vertice triangle doesnt fit the size it should :
Picture : http://i.stack.imgur.com/tH02H.png
My android screen resolution is 1280*800 I would just like to get this triangle with those vertices rotate without being modified this way.
Can someone explain me how to do this .
EDIT :
Thanks to Andon M. Coleman and SAKrisT , i was able to get my origin point to 0:0 android coordinate at the top left.
if it can help :
public void onDrawFrame(GL10 unused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.orthoM(mProjectionMatrix, 0, left, right, top, bottom, near, far);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 1.0f, 0.0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
Matrix.setRotateM(mRotationMatrix, 0, 0, 0, 0, 1.0f);
Matrix.multiplyMM(mProjectionMatrix, 0, mMVPMatrix, 0, mRotationMatrix, 0);
mTriangle.draw(mProjectionMatrix);
}

OpenGL ES Lighting (Matrix And/Or Normals issue)

I'm trying to add per vertex lighting in OpenGL ES and I'm encountering strange problems for which I didn't find solution.
I first used Android documentation to create shapes :
http://developer.android.com/training/graphics/opengl/index.html
Then I used learn opengl es to add lightinh :
http://www.learnopengles.com/android-lesson-two-ambient-and-diffuse-lighting/
So here is the code of my renderer :
#Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
// Enable depth testing
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
float[] coords = new float[]{
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f , 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f , 0.5f, 0.5f
};
short[] drawOrder = new short[]{
0,1,2,
0,2,3,
4,5,6,
4,6,7,
};
float[] normals = new float[]{
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
};
float[] colors = new float[]{
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
};
testSolid = new Solid(coords, drawOrder, colors, normals);
}
public void onDrawFrame(GL10 unused) {
float[] lightPos = new float[]{0.5f, 0.5f, -0.5f, 1.0f};
// Redraw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -5.0f, 0f, 0f, 0f, 0f, 2.0f, 0.0f);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.multiplyMM(mVMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.setIdentityM(mLightModelMatrix, 0);
Matrix.multiplyMV(mLightPosInWorldSpace, 0, mLightModelMatrix, 0, lightPos, 0);
Matrix.multiplyMV(mLightPosInEyeSpace, 0, mVMatrix, 0, mLightPosInWorldSpace, 0);
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 1.0f, 0.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mLightMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
// Combine the rotation matrix with the projection and camera view
Matrix.multiplyMM(mMVPMatrix, 0, mRotationMatrix, 0, mLightMatrix, 0);
// Draw shape
testSolid.draw(mVMatrix, mMVPMatrix, mLightPosInEyeSpace);
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
Then, my code for the Solid :
First, my program :
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"uniform mat4 uMVMatrix;"+
"uniform vec3 uLightPos;"+
"attribute vec3 aNormal;" +
"attribute vec4 aColor;" +
"attribute vec4 aPosition;" +
"varying vec4 vColor;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
" vec3 modelViewVertex = vec3(uMVMatrix * aPosition);"+
" vec3 modelViewNormal = vec3(uMVMatrix * vec4(aNormal, 0.0));"+
" float distance = length(uLightPos - modelViewVertex);"+
" vec3 lightVector = normalize(uLightPos - modelViewVertex);"+
" float diffuse = max(dot(modelViewNormal, lightVector), 0.1);"+
" diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance)));"+
" vColor = aColor * diffuse;"+
" gl_Position = aPosition * uMVPMatrix;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"varying vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
And my draw function :
public void draw(float[] mvMatrix, float[] mvpMatrix, float[] lightPos) {
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
// Positions
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, DATA_PER_VERTEX,
GLES20.GL_FLOAT, false,
0, vertexBuffer);
CubeRenderer.checkGlError(String.format("Positions (%d)", mPositionHandle));
// Colors
mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
GLES20.glEnableVertexAttribArray(mColorHandle);
GLES20.glVertexAttribPointer(mColorHandle, 4,
GLES20.GL_FLOAT, false,
0, colorBuffer);
CubeRenderer.checkGlError(String.format("Colors (%d)", mColorHandle));
// Normals
mNormalHandle = GLES20.glGetAttribLocation(mProgram, "aNormal");
GLES20.glVertexAttribPointer(mNormalHandle, 3,
GLES20.GL_FLOAT, false,
0, normalBuffer);
GLES20.glEnableVertexAttribArray(mNormalHandle);
CubeRenderer.checkGlError(String.format("Normals (%d)", mColorHandle));
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
CubeRenderer.checkGlError("glGetUniformLocation");
mMVMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVMatrix");
CubeRenderer.checkGlError("glGetUniformLocation");
mLightPosHandle = GLES20.glGetUniformLocation(mProgram, "uLightPos");
CubeRenderer.checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mvMatrix, 0);
GLES20.glUniform3f(mLightPosHandle, lightPos[0], lightPos[1], lightPos[2]);
CubeRenderer.checkGlError("glUniformMatrix4fv");
// Draw the polygon
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
But, when I run it, I have very strange result.
First, light is very dim, and not in good place
Second, I have a rotation with touch event, and if I rotate my shape, the light will also rotate.
May you know where this issue comes from ?
Thank you.

Scrolling in OpenGL ES 1.1

I'm developing a 2D side-scrolling game.I have a tiled bitmap for background with size 2400x480.How can i scroll this bitmap?
I know that i can do it with following code:
for(int i=0;i<100;i++)
draw(bitmap,2400*i,480);
So it will scroll bitmap for 240000 pixels.
But i don't want to draw images which stays out of screen(with size 800x480).
How can i render scrolling tile?How can i give velocity to it?(For parallax scrolling after normal scrolling)
The following code does not use two quads, but one quad, and adapts the texture coordinates accordingly. Please note that I stripped all texture handling code. The projection matrix solely contains glOrthof(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);. Quad2D defines a quad whose tex coords can be animated using updateTexCoords:
static class Quad2D {
public Quad2D() {
/* SNIP create buffers */
float[] coords = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, };
mFVertexBuffer.put(coords);
float[] texs = { 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, };
mTexBuffer.put(texs);
/* SNIP reposition buffer indices */
}
public void updateTexCoords(float t) {
t = t % 1.0f;
mTexBuffer.put(0, 0.33f+t);
mTexBuffer.put(2, 0.0f+t);
mTexBuffer.put(4, 0.33f+t);
mTexBuffer.put(6, 0.0f+t);
}
public void draw(GL10 gl) {
glVertexPointer(2, GL_FLOAT, 0, mFVertexBuffer);
glTexCoordPointer(2, GL_FLOAT, 0, mTexBuffer);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
/* SNIP members */
}
Now how to call updateTexCoords? Inside onDrawFrame, put the following code:
long time = SystemClock.uptimeMillis() % 3000L;
float velocity = 1.0f / 3000.0f;
float offset = time * velocity;
mQuad.updateTexCoords(offset);
Since the texture coordinates go beyond 1.0f, the texture wrap for the S coordinate must be set to GL_REPEAT.
If you are ok working with shaders, we can have a cleaner and may be more efficient way of doing this.
Create a VBO with a quad covering the whole screen. The witdth and height should be 800 and 480 respectively.
then create your vertex shader as:
attribute vec4 vPos;
uniform int shift;
varying mediump vec2 fTexCoord;
void main(void){
gl_Position = vPos;
fTexCoord = vec2((vPos.x-shift)/800.0, vPos.y/480.0);//this logic might change slightly based on which quadarnt you choose.
}
The fragment shader would be something like:
precision mediump float;
uniform sampler2D texture;
varying mediump vec2 fTexCoord;
void main(void){
gl_FragColor = texture2D(texture, fTexCoord);
}
and you are done.
To scroll just set the uniform value using "glUniformX()" apis.

Categories

Resources