Android OpenGL ES doesn't display my triangulated shape using TRIANGLES - android

I want to display shapes as different as one likes using OpenGL ES on an Android device. Problem is that my code doesn't even work for easy shapes like a rectangle (which I am going to use below).
I think somthing is wrong with the glTranslatef. I've adjusted all the values but I can't figure out what it is.
The Rectangle is defined by the points P(0,0,0), P(0,1,0), P(1,1,0), P(1,0,0). In the Activity I implemented the GLSurfaceView.Renderer like this:
private static FloatBuffer getVertexCoords() {
float coords[] = {
0f, 0f, 0f, // first triangle first point
0f, 1f, 0f, // first triangle second point
1f, 1f, 0f, // first triangle third point
1f, 1f, 0f, // second triangle first point
1f, 0f, 0f, // second triangle second point
0f, 0f, 0f, // second triangle third point
}
ByteBuffer vbb = ByteBuffer.allocateDirect(coords.length * 4); // n coords * 4 bytes per float
vbb.order(ByteOrder.nativeOrder());
FloatBuffer trianglesVB = vbb.asFloatBuffer();
trianglesVB.put(coords);
trianglesVB.position(0);
return trianglesVB;
}
#Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0f, 0f, -4f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); // glBegin
gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, getVertexCoords());
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 2 * 3 * 3); // triangles * points * coords
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // glEnd
int error = gl.glGetError();
if (error != GL10.GL_NO_ERROR) {
Log.e(TAG, "OpenGL ES Error: " + error);
}
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// think this one doesn't matter
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // white background
gl.glFrontFace(GL10.GL_CW); // front face is clockwise
}

I think you need a projection matrix in there somewhere. If you don't set one, then you are drawing directly in normalized device coordinates, of which the only valid z-values are from (-1 to 1).
Simply your triangle is outside of the depth range displayed.
Try adding a simple projection matrix to onSurfaceCreated:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-10, 10, -10, 10, 0, 10);

Related

OpenGl drag square

I'm creating a curtain like animation triggered by onTouchEvent() where u can drag one end of a square to make it bigger or smaller.
My only problem is that instead of having a square on the entire screen, I get a small line on the top of the screen and i can expand and de-expand that line.
Why won't this code draw a square?
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
float ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION); // set matrix to projection mode
gl.glLoadIdentity(); // reset the matrix to its default state
gl.glOrthof(0, height, width, 0, -3, 8);
}
Vertices:
private float vertices[] = {
-1.0f, 1.0f, 0.0f, // 0, Top Left
-1.0f, -1.0f, 0.0f, // 1, Bottom Left
1.0f, -1.0f, 0.0f, // 2, Bottom Right
1.0f, 1.0f, 0.0f, // 3, Top Right
};
// The order we like to connect them.
private short[] indices = { 0, 1, 2, 0, 2, 3 };
And the draw method in Square:
public void draw(GL10 gl,float x,float y) {
// Counter-clockwise winding.
gl.glFrontFace(GL10.GL_CCW); // OpenGL docs
//Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
//Enable vertex buffer
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);
//Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
You are missing this? after setting the projection mode.
gl.glMatrixMode(GL10.GL_MODELVIEW); // set modelview matrix to identity.
gl.glLoadIdentity();

drawing a square in open gles

ı try to draw a square.. but when ı run the code, ı see a tringle , not a square... :)) what is the problem here???
public class MyGL20Renderer implements GLSurfaceView.Renderer {
private FloatBuffer square1;
private void initShapes(){
float square1Coords[]={
-0.5f, -0.5f, 0.0f, // 0. left-bottom
0.5f, -0.5f, 0.0f, // 1. right-bottom
0.0f, 0.0f, 0.0f, // 2. left-top
0.5f, 0.5f, 0.0f // 3. right-top
};
// initialize vertex Buffer for square
ByteBuffer vbb4 = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
square1Coords.length * 4);
vbb4.order(ByteOrder.nativeOrder());
square1 = vbb4.asFloatBuffer();
square1.put(square1Coords);
square1.position(0);
}
.
.
.
.
public void onDrawFrame(GL10 gl) {
// Redraw background color
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Draw the square
gl.glColor4f(0.0f, 0.0f, 1.0f, 0.0f); //blue
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, square1);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 4);
}
You're specifying GL_TRIANGLES but only have four vertices. Try six.
Or use GL_TRIANGLE_STRIP.
Left top point seem to be wrong, should be -0.5, 0.5, 0.0 and I also agree with genpfault that think you should use GL_TRIANGLE_STRIP
ok.. ı found a way to solve the problem, ı think..
//this is our Square class
public class Square {
private FloatBuffer vertexBuffer; // buffer holding the vertices
private float vertices[] = {
-0.3f, -0.3f, 0.0f, // 0. left-bottom
0.3f, -0.3f, 0.0f, // 1. right-bottom
-0.3f, 0.3f, 0.0f, // 2. left-top
0.3f, 0.3f, 0.0f // 3. right-top
};
public Square() {
// a float has 4 bytes so we allocate for each coordinate 4 bytes
ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
vertexByteBuffer.order(ByteOrder.nativeOrder());
// allocates the memory from the byte buffer
vertexBuffer = vertexByteBuffer.asFloatBuffer();
// fill the vertexBuffer with the vertices
vertexBuffer.put(vertices);
// set the cursor position to the beginning of the buffer
vertexBuffer.position(0);
}
/** The draw method for the square with the GL context */
public void draw(javax.microedition.khronos.opengles.GL10 gl) {
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// set the colour for the square
gl.glColor4f(1.0f, 0.0f, 0.0f, 0.0f); //red
// Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
// Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
}
// and this is our renderer class
public class MyRenderer implements GLSurfaceView.Renderer {
// the square to be drawn
private Square square;
public MyRenderer() {
this.square = new Square();
#Override
public void onDrawFrame(GL10 gl) {
// clear Screen and Depth Buffer
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Reset the Modelview Matrix
gl.glLoadIdentity();
// Drawing
gl.glTranslatef(0.0f, 0.0f, -5.0f);
// Draw the square
square.draw(gl);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if(height == 0) { //Prevent A Divide By Zero By
height = 1; //Making Height Equal One
}
gl.glViewport(0, 0, width, height); //Reset The Current Viewport
gl.glMatrixMode(GL10.GL_PROJECTION); //Select The Projection Matrix
gl.glLoadIdentity(); //Reset The Projection Matrix
//Calculate The Aspect Ratio Of The Window
GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW); //Select The Modelview Matrix
gl.glLoadIdentity(); //Reset The Modelview Matrix
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}
}

android/openGL: fill a 2d viewport with a square

What I've managed to accomplish so far is:
Initialise the GLSurfaceView/Renderer
Draw a triangle on the screen
Render a square/rectangle on the screen
Add a bitmap texture to the screen
Ensure PNG transparency is honoured when rendering
Automatically scale the triangles so they show up correctly for all screen sizes
However, after fixing the scaled triangles, the background rectangle (with texture) no longer fills up the screen.
I've been stuck on this for a while now and absolutely baffled to the point I have thrown in the towel.
The main parts I'm unsure about is the use of glFrustumf() and gluLookAt().
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION); // set matrix to projection mode
gl.glLoadIdentity(); // reset the matrix to its default state
gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7); // apply the projection matrix
}
#Override
public void onDrawFrame(GL10 gl) {
// Clear the screen
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
// Set GL_MODELVIEW transformation mode
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity(); // reset the matrix to its default state
// When using GL_MODELVIEW, you must set the camera view
GLU.gluLookAt(gl, 0, 0, -5f, 0f, 0f, 0f, 0.0f, 1.0f, 0.0f);
bg.draw(gl);
// ...
}
If anybody has a moment to take a look at the problem, I've uploaded the files to https://bitbucket.org/koonkii/test_opengl/src so you don't have to recreate the code by copy-pasting.
GLU.gluLookAt(gl, 0, 0, -5f, 0f, 0f, 0f, 0.0f, 1.0f, 0.0f);
Try to change -5f to 0, what you're saying here is displace the camera 5 units back, therefore unless you're doing an orthogonal projection (which I think you're not, try checking out this) what OpenGL is doing is scaling your background polygon according to your perspective view, and you see it as 'smaller'.
If you do an orthogonal projection, no matter how much you move your camera in the z axis, you will always see it the same size. This is useful for 2D OpenGL-based games, so do check out the link above.
EDIT: gluPerspective and glOrtho
gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
gluPerspective has a parameter called 'fovy', which is basically the 'Field of View in the Y axis'. The field of view expresses the amount of space the camera can see, basically 'expanding' or 'contracting' whatever vertices happen to be before it. A typical human eye has a 45º FOV.
The zNear and zFar express the near and far frustum limits, the frustum being an invisible 'box' which determines which vertices are outside the viewing area.
Aspect determines the ratio between the width and height of the camera.
glOrtho is a special case of gluPerspective in the sense that the FOV is always 0.
gl.glOrthof(0.0f, (float) width, (float) height, 0.0f, 1.0f, -1.0f);
The first four parameters specify the size of the clipping plane (normally the size of the screen), the other two values specifiy the frustum near and far (which you don't need unless you want to hide objects by placing them 'far away'.
I hope this cleared it up a bit for you.
Alright, after a good nights sleep and applying RedOrav's advice regarding orthogonal projection, I did more browsing into it and got it working!
The code snippets given by RedOrav did actually work, however after switching to the orthogonal projection I was still drawing the squares and triangles as small as 0.15f in width. Barely be visible as it's less than 1 pixel wide!
After changing the background/square/triangle code to something more reasonable (30.0f), they showed up!
Played around with the code a bit more and got positioning working properly. I've submitted the code to bitbucket for those who want to check out a working copy of the project.
The reason why I needed G.getYPos() is because the bottom coordinate = 0, and top is screen height. Couldn't figure out a nicer way of inverting it without turning all the textures upside-down.
The important initialisation parts are:
Global helper
public class G {
public static float ratio;
public static int width, height;
/** The texture pointer */
public static int[] textures = new int[3];
final static int TEXTURE_DEFAULT = 0;
final static int TEXTURE_BG = 1;
final static int TEXTURE_ANDROID = 2;
final static int TEXTURE_TURTLE = 3;
/**
* Since (bottom = 0, top = height), we need to invert the values so they make sense logically.
*/
public static int getYPos(int top) {
return G.height - top;
}
}
Renderer class
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
this.loadGLTextures(gl);
gl.glClearColor(1.0f, 0.0f, 0.0f, 1.0f); //Red Background
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
// Save these for global use.
G.width = width;
G.height = height;
G.ratio = (float) width / height;
// Set up orthogonal viewport and make adjustments for screen ratio
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluOrtho2D(gl, 0, width, 0, height); // The parameters are weird but bottom = 0 so we need an inverter function G.
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
// Start setting up the constructs we need
bg = new Background();
squares = new ArrayList<Square>();
squares.add(new Square(width / 2, G.getYPos(0))); // middle/top of the screen
squares.add(new Square(width / 2, G.height /2)); // center of the screen
triangles = new ArrayList<Triangle>();
triangles.add(new Triangle(0, G.getYPos(0))); // top left
triangles.add(new Triangle(width, G.getYPos(height))); // bottom right
triangles.add(new Triangle(width /2, height /2)); // middle
}
#Override
public void onDrawFrame(GL10 gl) {
// Clear the screen
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
bg.draw(gl);
for (Square s : squares) {
s.draw(gl);
}
// Draw correctly scaled triangles
for (Triangle t : triangles) {
t.draw(gl);
}
try {
Thread.sleep(400);
}
catch (InterruptedException e) {
}
}
/**
* Loads the textures up.
*/
public void loadGLTextures(GL10 gl) {
int[] texture_map = new int[] { R.drawable.bg_game, R.drawable.ic_launcher };
Bitmap bitmap;
// generate one texture pointer, keep 0 as blank/default
gl.glGenTextures(texture_map.length, G.textures, 0);
for (int i = 0; i < texture_map.length; i++) {
// loading texture
bitmap = BitmapFactory.decodeResource(context.getResources(), texture_map[i]);
// ...and bind it to our array
gl.glBindTexture(GL10.GL_TEXTURE_2D, G.textures[i +1]);
// create nearest filtered texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
// Use Android GLUtils to specify a two-dimensional texture image from our bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
// Clean up
bitmap.recycle();
}
}
Background class
p
ublic class Background {
private FloatBuffer vertexBuffer; // buffer holding the vertices
private float vertices[] = {
-1.0f, -1.0f, 0.0f, // V1 - bottom left
-1.0f, 1.0f, 0.0f, // V2 - top left
1.0f, -1.0f, 0.0f, // V3 - bottom right
1.0f, 1.0f, 0.0f // V4 - top right
};
private FloatBuffer textureBuffer; // buffer holding the texture coordinates
private float texture[] = {
// Mapping coordinates for the vertices
0.0f, 1.0f, // top left (V2)
0.0f, 0.0f, // bottom left (V1)
1.0f, 1.0f, // top right (V4)
1.0f, 0.0f // bottom right (V3)
};
public Background() {
// Recalculate the vertices so they fit the screen
vertices[0] = 0; // v1 left
vertices[1] = G.height; // v1 bottom
vertices[3] = 0; // v2 left
vertices[4] = 0; // v2 top
vertices[6] = G.width; // v3 right
vertices[7] = G.height; // v3 bottom
vertices[9] = G.width; // v4 right
vertices[10] = 0; // v4 top
// a float has 4 bytes so we allocate for each coordinate 4 bytes
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
// allocates the memory from the byte buffer
vertexBuffer = byteBuffer.asFloatBuffer();
// fill the vertexBuffer with the vertices
vertexBuffer.put(vertices);
// set the cursor position to the beginning of the buffer
vertexBuffer.position(0);
byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
}
public void draw(GL10 gl) {
gl.glEnable(GL10.GL_TEXTURE_2D); // Twig;
// Bind the previously generated texture
gl.glBindTexture(GL10.GL_TEXTURE_2D, G.textures[G.TEXTURE_BG]);
// Point to our buffers
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
// Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisable(GL10.GL_TEXTURE_2D); // twig;
}
}
Square class
Very similar to background except it has a position and applies alpha transparency.
public class Square {
private FloatBuffer vertexBuffer; // buffer holding the vertices
private float vertices[] = {
-1.0f, -1.0f, 0.0f, // V1 - bottom left
-1.0f, 1.0f, 0.0f, // V2 - top left
1.0f, -1.0f, 0.0f, // V3 - bottom right
1.0f, 1.0f, 0.0f // V4 - top right
};
private FloatBuffer textureBuffer; // buffer holding the texture coordinates
private float texture[] = {
// Mapping coordinates for the vertices
0.0f, 1.0f, // top left (V2)
0.0f, 0.0f, // bottom left (V1)
1.0f, 1.0f, // top right (V4)
1.0f, 0.0f // bottom right (V3)
};
public Square(float posX, float posY) {
float w = 30f;
float h = w;
vertices[0] = posX - w; // left
vertices[3] = posX - w;
vertices[6] = posX + w; // right
vertices[9] = posX + w;
vertices[1] = posY - h; // top
vertices[4] = posY + h;
vertices[7] = posY - h; // bottom
vertices[10] = posY + h;
// a float has 4 bytes so we allocate for each coordinate 4 bytes
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
// allocates the memory from the byte buffer
vertexBuffer = byteBuffer.asFloatBuffer();
// fill the vertexBuffer with the vertices
vertexBuffer.put(vertices);
// set the cursor position to the beginning of the buffer
vertexBuffer.position(0);
byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
}
/** The draw method for the square with the GL context */
public void draw(GL10 gl) {
// Enable alpha transparency
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
// bind the previously generated texture
gl.glEnable(GL10.GL_TEXTURE_2D); // Twig;
gl.glBindTexture(GL10.GL_TEXTURE_2D, G.textures[G.TEXTURE_ANDROID]);
// Point to our buffers
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// reset the colour for the square
gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
// Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
// Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// Disable alpha transparency
gl.glDisable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ZERO);
gl.glDisable(GL10.GL_TEXTURE_2D); // twig;
}
}
Triangle class
public class Triangle {
private FloatBuffer vertexBuffer; // buffer holding the vertices
private float vertices[] = {
-0.5f, -0.5f, 0.0f, // V1 - first vertex (x,y,z)
0.5f, -0.5f, 0.0f, // V2 - second vertex
0.0f, 0.5f, 0.0f // V3 - third vertex
};
public Triangle(float posX, float posY) {
int w = 30;
int h = w;
vertices[0] = posX - (w/2); // left
vertices[3] = posX + (w/2); // right
vertices[6] = posX; // middle
vertices[1] = posY - (h/2); // bottom
vertices[4] = posY - (h/2); // bottom
vertices[7] = posY + (h/2); // top
// a float has 4 bytes so we allocate for each coordinate 4 bytes
ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
vertexByteBuffer.order(ByteOrder.nativeOrder());
// allocates the memory from the byte buffer
vertexBuffer = vertexByteBuffer.asFloatBuffer();
// fill the vertexBuffer with the vertices
vertexBuffer.put(vertices);
// set the cursor position to the beginning of the buffer
vertexBuffer.position(0);
}
public void draw(GL10 gl) {
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// set the colour for the triangle
gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
// Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
// Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
// Reset the colour
gl.glColor4f(1.0f, 1.0f, 1.0f, 0.0f);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
}
Hope this helps anyone else having similar issues with starting OpenGL.

OpenGL 2D colors gone wrong

I am having problems with my simple 2D OpenGL game.
Its really weird, I get textures to display correctly etc. but when I wanted to create particle effect with simple changing colors, for some reason it displays wrong colors from the buffer. I am using Android's OpenGL ES 1.1 but its the same with any version of OpenGL that uses VBO's.
I initialize the screen etc. and red triangle is displayed, but according to my color buffer it should be white, whats wrong?
GL11 gl11 = (GL11) gl;
gl11.glLoadIdentity();
gl11.glClear(GL_COLOR_BUFFER_BIT);
GLU.gluLookAt(gl, 0f, 0f, -container.getCamera().getScale(), 0f, 0f, 0f, 0f, -1f, 0f);
gl11.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl11.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl11.glTranslatef(container.getCamera().getX(), container.getCamera().getY(), 0.0f);
container.addParticle(new ColouredParticle(-container.getCamera().getX(), -container.getCamera().getY(), (float)Math.random(), (float)Math.random(), 0f, 5000));
particleColorBufferPointer = createFloatBuffer(gl11, GL11.GL_ARRAY_BUFFER, new float[] {
1f, 1f, 1f, 1f,
1f, 1f, 1f, 1f,
1f, 1f, 1f, 1f,
});
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, particleColorBufferPointer);
gl11.glColorPointer(4, GL10.GL_FLOAT, 0, 0);
particleVertexBufferPointer = createFloatBuffer(gl11, GL11.GL_ARRAY_BUFFER, new float[]{
-0.1f, -0.05f,
0.1f, -0.05f,
0.0f, 0.05f
});
gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, particleVertexBufferPointer);
gl11.glVertexPointer(2, GL10.GL_FLOAT, 0, 0);
gl11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);
gl11.glDeleteBuffers(2, new int[]{particleVertexBufferPointer, particleColorBufferPointer}, 0);
gl11.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl11.glDisableClientState(GL10.GL_COLOR_ARRAY);
int error = gl11.glGetError();
if(error != GL11.GL_NO_ERROR) {
Log.v(TAG, "error " + Integer.toHexString(error));
}
Its just simple hardcoded float array containing the triangle vertices and colors, but for some reason the colors are wrong as I said before, what can possibly go wrong with such small amount of code? the color doesn't change to anything but black, like it only reads the red value from the buffer. Also it gives absolutely no error at all!
createFloatBuffer method:
private int createFloatBuffer(GL11 gl, int type, float[] data) {
int[] bufferPointerBuffer = new int[1];
gl.glGenBuffers(1, bufferPointerBuffer, 0);
int bufferPointer = bufferPointerBuffer[0];
gl.glBindBuffer(type, bufferPointer);
FloatBuffer dataBuffer = createFloatBuffer(data);
gl.glBufferData(type, data.length * FLOAT_SIZE, dataBuffer, GL_STATIC_DRAW);
gl.glBindBuffer(type, -1);
return bufferPointer;
}
Wow.. It all was because I had texture bound and it for some reason tried to draw it even if I had texture coords disabled, I wish i could have just listened when I got told to disable any state thats not needed anymore.. Thanks guys! Problem solved!

Problem with GL_TRIANGLES

i am working on a program which draws polygons according to user inputs.
I have problems with drawing triangles using GL_TRIANGLE. I used the same code below to draw square and it worked well. Hovewer, if i want to draw only one triangle it does not work.
Can anyone help me?
public class Triangle extends Shape{
private FloatBuffer vertexBuffer;
private FloatBuffer _colorBuffer;
private ShortBuffer indexBuffer;
private float vertices[] = {
-0.5f, -0.5f, 0.5f, // 0
0.5f, -0.5f, 0.5f, // 1
0f, -0.5f, -0.5f, // 2
};
private short[] indices = { 0, 2, 1 };
float[] colors = {1f, 1f, 0f, 1f };
public Triangle() {
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
cbb.order(ByteOrder.nativeOrder());
_colorBuffer = cbb.asFloatBuffer();
_colorBuffer.put(colors);
_colorBuffer.position(0);
}
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CCW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,GL10.GL_UNSIGNED_SHORT, indexBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
}
edit:
i call my Triangle class from here, maybe i have made mistake here
public class OpenGLRenderer implements Renderer {
String name;
ArrayList myArr ;
private float angle, x,y,z;
public OpenGLRenderer(String nm ) {
name =nm;
myArr = new ArrayList<Shape>();
x=0;
y=0;
z=-3;
}
#Override
public void onDrawFrame(GL10 gl) {
//clear the screen and depth buffer
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glTranslatef(x, y, z);
for (Shape t : myArr)
{
if (t instanceof Rectangle)
{
// gl.glTranslatef(0, 0, -4);
((Rectangle )t).draw(gl);
}
if (t instanceof Square)
{ //gl.glTranslatef(0, 1, 0);
((Square )t).draw(gl);}
if (t instanceof Pyramid){
((Pyramid)t).draw(gl);
if (t instanceof Triangle){
((Triangle)t).draw(gl);
}
if (t instanceof Line){
((Line)t).draw(gl);
}
}
}//for
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity(); //reset the projection matrix
GLU.gluPerspective(gl, 45.0f, (float)width/(float)height,
0.1f, 100.0f); //calculate the aspect ratio of window
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//set the bg as black
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
gl.glShadeModel(GL10.GL_SMOOTH);
//depth buffer setup
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
}
public void addshape(Shape s)
{y=y+0.1f;
myArr.add(s);
}
}
It looks to me like you don't have enough colors in your colors array. This might result in an invisible triangle depending on the initial garbage values in your _colorBuffer.
(Edit) try:
float[] colors = {
1f, 1f, 0f, 1f,
1f, 1f, 0f, 1f,
1f, 1f, 0f, 1f
};
First, Martin is correct about the colors array. It needs to have a color (4 values in your case) for every vertex (so 12 values at all).
Next, at the moment your triangle lies inside the x-z-plane and as you don't make any changes to the modelview matrix (except translating along the z-axis), you should just see a line, if any, (think of a sheet of paper viewed from the side).
But your real problem is your draw loop. I guess you're not only new to OpenGL, but also to Java and object oriented programming in general. This whole design is complete rubbish. That's what virtual functions are for in object oriented code. Just let each shape implement its correct draw method. So the only thing you need to do is
for (Shape t : myArr)
t.draw(gl);
Given that Shape has an abstract draw method, that the other subclasses implement. But this is more of a design flaw. The actual error is, that the braces of the ifs are broken. At the moment the triangle is only drawn, if t is an instance of Pyramid and of Triangle, so draw is never called for triangles (and also for lines).
here my triangle code from a project which works. Looks like your indices and colour arrays are different
package com.martynhaigh.Vortex;
import android.view.animation.Transformation;
import javax.microedition.khronos.opengles.GL10;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
public class Triangle {
private ShortBuffer _indexBuffer;
private FloatBuffer _vertexBuffer;
private FloatBuffer _colorBuffer;
static float _xAngle, _yAngle;
private int _nrOfVertices;
Triangle() {
float[] coords = {
-0.5f, -0.5f, 0f, // (x1, y1, z1)
0.5f, -0.5f, 0f, // (x2, y2, z2)
0f, 0.5f, 0f // (x3, y3, z3)
}; // 9
_nrOfVertices = coords.length / 3;
float[] colors = {
1f, 0f, 0f, 1f, // point 1
0f, 1f, 0f, 1f, // point 2
0f, 0f, 1f, 1f // point 3
}; // 12
short[] indices = {0, 1, 2}; // 3
// float has 4 bytes, coordinate * 4 bytes
ByteBuffer vbb = ByteBuffer.allocateDirect(coords.length * 4); //36
vbb.order(ByteOrder.nativeOrder());
_vertexBuffer = vbb.asFloatBuffer();
// short has 2 bytes, indices * 2 bytes
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2); // 6
ibb.order(ByteOrder.nativeOrder());
_indexBuffer = ibb.asShortBuffer();
// float has 4 bytes, colors (RGBA) * 4 bytes
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4); // 48
cbb.order(ByteOrder.nativeOrder());
_colorBuffer = cbb.asFloatBuffer();
_vertexBuffer.put(coords);
_indexBuffer.put(indices);
_colorBuffer.put(colors);
_vertexBuffer.position(0);
_indexBuffer.position(0);
_colorBuffer.position(0);
}
public void onDraw(GL10 gl) {
// set rotation
gl.glRotatef(_xAngle, 1f, 0f, 0f);
gl.glRotatef(_yAngle, 0f, 1f, 0f);
// set the color of our element
//gl.glColor4f(0.5f, 0f, 0f, 0.5f);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);
// define the vertices we want to draw
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);
// finally draw the vertices
gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);
}
public void setXAngle(float angle) {
_xAngle = angle;
}
public float getXAngle() {
return _xAngle;
}
public void setYAngle(float angle) {
_yAngle = angle;
}
public float getYAngle() {
return _yAngle;
}
}

Categories

Resources