Related
This is the actual code from NeHe's ports but it isn't drawing anything. Why ??
My main activity class :
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
/**
* Our OpenGL program's main activity
*/
public class Main extends Activity {
private GLSurfaceView glView; // Use GLSurfaceView
// Call back when the activity is started, to initialize the view
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
glView = new GLSurfaceView(this); // Allocate a GLSurfaceView
glView.setEGLContextClientVersion(1);
glView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
glView.setRenderer(new mainRenderer(this)); // Use a custom renderer
this.setContentView(glView); // This activity sets to GLSurfaceView
}
// Call back when the activity is going into the background
#Override
protected void onPause() {
super.onPause();
glView.onPause();
}
// Call back after onPause()
#Override
protected void onResume() {
super.onResume();
glView.onResume();
}
}
My renderer class :
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
/**
* OpenGL Custom renderer used with GLSurfaceView
*/
public class mainRenderer implements GLSurfaceView.Renderer {
Context context; // Application's context
Patrat quad;
// Constructor with global application context
public mainRenderer(Context context) {
this.context = context;
quad = new Patrat();
}
// Call back when the surface is first created or re-created
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set color's clear-value to black
gl.glClearDepthf(1.0f); // Set depth's clear-value to farthest
gl.glEnable(GL10.GL_DEPTH_TEST); // Enables depth-buffer for hidden surface removal
gl.glDepthFunc(GL10.GL_LEQUAL); // The type of depth testing to do
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); // nice perspective view
gl.glShadeModel(GL10.GL_SMOOTH); // Enable smooth shading of color
gl.glDisable(GL10.GL_DITHER); // Disable dithering for better performance
// You OpenGL|ES initialization code here
// ......
}
// Call back after onSurfaceCreated() or whenever the window's size changes
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if (height == 0) height = 1; // To prevent divide by zero
float aspect = (float)width / height;
// Set the viewport (display area) to cover the entire window
gl.glViewport(0, 0, width, height);
// Setup perspective projection, with aspect ratio matches viewport
gl.glMatrixMode(GL10.GL_PROJECTION); // Select projection matrix
gl.glLoadIdentity(); // Reset projection matrix
// Use perspective projection
GLU.gluPerspective(gl, 45, aspect, 0.1f, 100.f);
gl.glMatrixMode(GL10.GL_MODELVIEW); // Select model-view matrix
gl.glLoadIdentity(); // Reset
// You OpenGL|ES display re-sizing code here
// ......
}
// Call back to draw the current frame.
#Override
public void onDrawFrame(GL10 gl) {
// Clear color and depth buffers using clear-value set earlier
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// You OpenGL|ES rendering code here
// ......
gl.glLoadIdentity();
quad.draw(gl);
}
}
My square class :
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
/*
* A square drawn in 2 triangles (using TRIANGLE_STRIP).
*/
public class Patrat {
private FloatBuffer vertexBuffer; // Buffer for vertex-array
private float[] vertices = { // Vertices for the square
-1.0f, -1.0f, 0.0f, // 0. left-bottom
1.0f, -1.0f, 0.0f, // 1. right-bottom
-1.0f, 1.0f, 0.0f, // 2. left-top
1.0f, 1.0f, 0.0f // 3. right-top
};
// Constructor - Setup the vertex buffer
public Patrat() {
// Setup vertex array buffer. Vertices in float. A float has 4 bytes
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder()); // Use native byte order
vertexBuffer = vbb.asFloatBuffer(); // Convert from byte to float
vertexBuffer.put(vertices); // Copy data into buffer
vertexBuffer.position(0); // Rewind
}
// Render the shape
public void draw(GL10 gl) {
// Enable vertex-array and define its buffer
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
// Draw the primitives from the vertex-array directly
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
}
Any solutions please ? I can't undersant why this doesn't work ...
1st off change vertices set 10% from yours:
private float[] vertices = { // Vertices for the square
-0.1f, -0.1f, 0.0f, // 0. left-bottom
0.1f, -0.1f, 0.0f, // 1. right-bottom
-0.1f, 0.1f, 0.0f, // 2. left-top
0.1f, 0.1f, 0.0f // 3. right-top
};
After that I found problem in your onDrawFrame(GL10 gl):
You don't have nor glTranslatef neitherglScalef
change it to:
#Override
public void onDrawFrame(GL10 gl) {
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, -1.0f); // move 5 units INTO the screen
// is the same as moving the camera 5 units away
gl.glScalef(0.5f, 0.5f, 0.5f); // scale the triangle to 50%
// otherwise it will be too large
quad.draw(gl);
}
I want to change position of object in OpenGL,I found this class and i want to write function change.When program call change i want to change positon of object
This class create a square and texture over...And i want to change position in pixels...
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)
};
private FloatBuffer textureBuffer1; // buffer holding the texture coordinates
private float texture1[] = {
// Mapping coordinates for the vertices
2.0f, 1.0f, // top left (V2)
2.0f, 0.0f, // bottom left (V1)
1.0f, 1.0f, // top right (V4)
1.0f, 0.0f // bottom right (V3)
};
/** The texture pointer */
private int[] textures = new int[1];
public Square() {
// 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);
byteBuffer = ByteBuffer.allocateDirect(texture1.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer1 = byteBuffer.asFloatBuffer();
textureBuffer1.put(texture1);
textureBuffer1.position(0);
}
/**
* Load the texture for the square
* #param gl
* #param context
*/
public void loadGLTexture(GL10 gl, Context context) {
// loading texture
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
R.drawable.a);
// generate one texture pointer
gl.glGenTextures(1, textures, 0);
// ...and bind it to our array
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
// 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();
}
/** The draw method for the square with the GL context */
public void draw(GL10 gl) {
// bind the previously generated texture
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
// Point to our buffers
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// Set the face rotation
gl.glFrontFace(GL10.GL_CW);
// 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);
}
}
OpenGL is a drawing API not a scene graph. In OpenGL there are no models, objects or scene. There are only points, lines and triangles, drawn to a pixel based framebuffer. What this means is, that every change in your scene must be complemented by a full redraw of the scene.
So if you want to move something on the screen, you change the value variable(s) controlling the position and do a full redraw.
ı 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) {
}
}
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.
I'm trying to make my first App. based on OpenGl, i'm trying to draw a triangle, and wHEN
RUNNING THE App. it just displays black screen with no triangle.
1-I dont know where my mistake is?
2-is there any good book/tutorials for beginners to opengl es Android?
Triangle Class:
public class Triangle {
private FloatBuffer vertxBuffer;
protected static byte indices[] = {
//Face definition:
0,1,3, //lower-right triangle of the face is drawn with vertices vertices[0]->vertices[1]->vertices[3] (->vertices[0])
0,3,2 //upper-right triangle of the face is drawn with vertices vertices[0]->vertices[3]->vertices[2] (->vertices[0])
};
public float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
public Triangle() {
// float has 4 bytes, so we allocate for each coordinate 4 bytes.
//what is the difference between ByteBuffer.allocateDirect AND ByteBuffer.allocate???
ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
vertexByteBuffer.order(ByteOrder.nativeOrder());
// allocate the memory from the byte buffer
vertxBuffer = vertexByteBuffer.asFloatBuffer();
//fill the vertex buffer with the vertices
vertxBuffer.put(vertices);
// set the cursor position to the beginning of the buffer
vertexByteBuffer.position(0);
}
protected static ByteBuffer indexBuffer;
static {
indexBuffer = ByteBuffer.allocateDirect(indices.length);
indexBuffer.put(indices);
indexBuffer.position(0);
}
public void draw(GL10 gl) {
// Because we store the Triangle vertices " Coordinates " in a FloatBuffer
// we need to enable OpenGL to read from it.
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//set the color for the Triangle (r, g, b, alpha) alpha is between 0-1
gl.glColor4f(2.0f, 1.0f, 0.0f, 0.5f);
// point to our vertex buffer to extract the vertices from it.
//(numberOfVertices, Which type of data the buffer Holds, offset, our Buffer containing the Vertices)
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertxBuffer);
//draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length/3 );
gl.glDrawElements(gl.GL_TRIANGLES, indices.length, gl.GL_UNSIGNED_BYTE, indexBuffer);
//disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
}
GLRenderer Class:
public class GLRenderer implements Renderer{
private Triangle triangle;
public GLRenderer() {
this.triangle = new Triangle();
}
#Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
// clear screen and depth buffer
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// reset the mode view matrix
gl.glLoadIdentity();
// Drawing
gl.glTranslatef(0.0f, 0.0f, -5.0f);
triangle.draw(gl);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
if (height == 0) {
height = 1;
}
//Reset the current View Port
gl.glViewport(0, 0, width, height);
//Select the Projection Matrix
gl.glMatrixMode(GL10.GL_PROJECTION);
// Reset the Projection Matrix
gl.glLoadIdentity();
// 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);
gl.glLoadIdentity();
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
gl.glClearColor(0, 0, 0, 1.0f);
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);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glDisable(GL10.GL_DITHER);
}
}
OpenGlRenderActivity Class:
public class OpenGLRenderActivity extends Activity {
/** Called when the activity is first created. */
private GLSurfaceView gLSurfaceView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
gLSurfaceView = new GLSurfaceView(this);
gLSurfaceView.setRenderer(new GLRenderer());
setContentView(gLSurfaceView);
}
#Override
protected void onResume() {
super.onResume();
gLSurfaceView.onResume();
}
#Override
protected void onPause() {
super.onPause();
gLSurfaceView.onPause();
}
}
I think you need to declare the indexes for your vertex (in order to compose the lines and faces):
protected static byte indices[] = {
//Face definition:
0,1,3, //lower-right triangle of the face is drawn with vertices vertices[0]->vertices[1]->vertices[3] (->vertices[0])
0,3,2 //upper-right triangle of the face is drawn with vertices vertices[0]->vertices[3]->vertices[2] (->vertices[0])
};
protected static ByteBuffer indexBuffer;
static {
indexBuffer = ByteBuffer.allocateDirect(indices.length);
indexBuffer.put(indices);
indexBuffer.position(0);
}
then pass those indexes to your draw call:
(replace
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length/3 );
with
gl.glDrawElements(GL.GL_TRIANGLES, indices.length, GL.GL_UNSIGNED_BYTE, indexBuffer);
)
As for tutorials you've got great Android versions of the Nehe tutorials here:
http://insanitydesign.com/wp/projects/nehe-android-ports/
It's more code than textual explanations, but they start you off real slow, and the code is well comented. Actually I think one of the first tutrials simply shows how to draw a triangle just like you're trying here.
Your triangles gets clipped by the near clipping plane. Try moving it into the range between the near and far values of gluPerspective.
This android tutorial mentions the requirement of a vertexShader, fragmentShader and Program. I may have missed it, but I don't see anything related to that in your code. In my case the fix for the invisible triangle was to fix a type-o in my fragmentShader.