Related
I began to try to draw VBO using JOGL. Prior to that, I drew with the help of glBegin and glEnd, and everything worked. And then I see only a black screen. What could be the problem? I read somewhere that using VBO for drawing requires shaders. Is it so?
Code:
public class Main implements GLEventListener {
public static DisplayMode dm, dm_old;
private GLU glu = new GLU();
private float xrot,yrot,zrot;
private int texture;
Texture t;
#Override
public void display(GLAutoDrawable drawable) {
final GL2 gl = drawable.getGL().getGL2();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity(); // Reset The View
gl.glTranslatef(0f, 0f, -5.0f);
gl.glBindTexture(GL2.GL_TEXTURE_2D, texture);
final float[] coordData = {
0, 0, //
1, 0, //
0, 1, //
};
final float[] vertices = {
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
};
// Setup the vertices into the buffer
FloatBuffer verts = Buffers.newDirectFloatBuffer(vertices.length);
verts.put(vertices).position(0);
// Setup the texture coordinates
FloatBuffer coords = Buffers.newDirectFloatBuffer(coordData.length);
coords.put(coordData).position(0);
gl.glVertexPointer(3, GL2.GL_FLOAT, 0, verts);
gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, coords);
gl.glDrawArrays(GL2.GL_TRIANGLES, 0, 3);
//change the speeds here
xrot += 5f;
}
#Override
public void init(GLAutoDrawable drawable) {
final GL2 gl = drawable.getGL().getGL2();
gl.glShadeModel(GL2.GL_SMOOTH);
gl.glClearColor(0f, 0f, 0f, 0f);
gl.glClearDepth(1.0f);
gl.glEnable(GL2.GL_DEPTH_TEST);
gl.glDepthFunc(GL2.GL_LEQUAL);
gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);
gl.glEnable(GL2.GL_TEXTURE_2D);
try {
File im = new File("/home/congard/pic/t.jpeg");
t = TextureIO.newTexture(im, true);
texture= t.getTextureObject(gl);
}catch(IOException e){
e.printStackTrace();
}
}
#Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
// some code
}
}
You didn't enable the client-side capabilities for vertex and texture coordinates. See Client-Side Vertex Arrays
and glEnableClientState.
Add the following to your code:
gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3, GL2.GL_FLOAT, 0, verts);
gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, coords);
I have a 2D OpenGL project for android of a .png as a texture on a Square. I would like to replicate the effect on all 6 sides of a 3D cube. I tried matching the format as closely as possible, but ran into a unexpected stopping issue.
My first code block:
package book.BouncySquare;
import android.content.Context;
import android.graphics.*;
import android.opengl.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
/**
* A vertex shaded square.
*/
class Square
{
public Square()
{
float vertices[] =
{
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f
};
byte maxColor=(byte)255;
byte colors[] =
{
maxColor,maxColor, 0,maxColor,
0, maxColor,maxColor,maxColor,
0, 0, 0,maxColor,
maxColor, 0,maxColor,maxColor
};
byte indices[] =
{
0, 3, 1,
0, 2, 3
};
float[] textureCoords =
{
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f
};
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
mFVertexBuffer = vbb.asFloatBuffer();
mFVertexBuffer.put(vertices);
mFVertexBuffer.position(0);
mColorBuffer = ByteBuffer.allocateDirect(colors.length);
mColorBuffer.put(colors);
mColorBuffer.position(0);
mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
mIndexBuffer.put(indices);
mIndexBuffer.position(0);
ByteBuffer tbb = ByteBuffer.allocateDirect(textureCoords.length * 4);
tbb.order(ByteOrder.nativeOrder());
mTextureBuffer = tbb.asFloatBuffer();
mTextureBuffer.put(textureCoords);
mTextureBuffer.position(0);
}
public void draw(GL10 gl)
{
gl.glVertexPointer(2, GL10.GL_FLOAT, 0, mFVertexBuffer);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glColorPointer(4, GL10.GL_UNSIGNED_BYTE, 0, mColorBuffer);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glEnable(GL10.GL_TEXTURE_2D); //1
gl.glEnable(GL10.GL_BLEND); //2
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_SRC_COLOR); //3
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); //4
gl.glTexCoordPointer(2, GL10.GL_FLOAT,0, mTextureBuffer); //5
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); //6
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); //7
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); //8
}
private int[] textures = new int[1];
public int createTexture(GL10 gl, Context contextRegf, int resource)
{
Bitmap tempImage = BitmapFactory.decodeResource(contextRegf.getResources(), resource); // 1
gl.glGenTextures(1, textures, 0); // 2
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); // 3
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, tempImage, 0); // 4
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); // 5a
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); // 5b
tempImage.recycle();//6
return resource;
}
private Float mTransY;
public FloatBuffer mTextureBuffer;
private FloatBuffer mFVertexBuffer;
private ByteBuffer mColorBuffer;
private ByteBuffer mIndexBuffer;
}
My second code block:
package book.BouncyCube1;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
import android.view.MotionEvent;
/**
* A vertex shaded cube.
*/
class Cube
{
float[] mVertices =
{
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f, -1.0f,-1.0f,
-1.0f, -1.0f,-1.0f
};
float maxColor=1.0f;
float[] mColors =
{
maxColor, maxColor, 0.0f,maxColor,
0.0f, maxColor, maxColor,maxColor,
0.0f, 0.0f, 0.0f,maxColor,
maxColor, 0.0f, maxColor,maxColor,
maxColor, 0.0f, 0.0f,maxColor,
0.0f, maxColor, 0.0f,maxColor,
0.0f, 0.0f, maxColor,maxColor,
0.0f, 0.0f, 0.0f,maxColor
};
float[] mNormals =
{
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.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, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
};
byte[] tfan1 =
{
1,0,3,
1,3,2,
1,2,6,
1,6,5,
1,5,4,
1,4,0
};
byte[] tfan2 =
{
7,4,5,
7,5,6,
7,6,2,
7,2,3,
7,3,0,
7,0,4
};
public Cube()
{
mTfan1 = ByteBuffer.allocateDirect(tfan1.length);
mTfan1.put(tfan1);
mTfan1.position(0);
mTfan2 = ByteBuffer.allocateDirect(tfan2.length);
mTfan2.put(tfan2);
mTfan2.position(0);
}
public void draw(GL10 gl)
{
gl.glVertexPointer(3, GL11.GL_FLOAT, 0,makeFloatBuffer(mVertices));
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glColorPointer(4, GL11.GL_FLOAT, 0,makeFloatBuffer(mColors));
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glNormalPointer(GL11.GL_FLOAT, 0,makeFloatBuffer(mNormals));
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDrawElements( gl.GL_TRIANGLE_FAN, 6 * 3, gl.GL_UNSIGNED_BYTE, mTfan1);
gl.glDrawElements( gl.GL_TRIANGLE_FAN, 6 * 3, gl.GL_UNSIGNED_BYTE, mTfan2);
}
protected static FloatBuffer makeFloatBuffer(float[] arr)
{
ByteBuffer bb = ByteBuffer.allocateDirect(arr.length*4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer fb = bb.asFloatBuffer();
fb.put(arr);
fb.position(0);
return fb;
}
private FloatBuffer mFVertexBuffer;
private FloatBuffer mNormalBuffer;
private ByteBuffer mColorBuffer;
private ByteBuffer mIndexBuffer;
private ByteBuffer mTfan1;
private ByteBuffer mTfan2;
}
OpenGL only supports one set of indices for a draw call, and these indices are used to address all vertex attributes (positions, colors, normals). Looking at your second version, you have 8 positions, 8 colors, and 12 normals. One way to notice that this can't work is that the range of your indices is 0..7, so not all of your 12 normals are used.
What you need to do is create a OpenGL vertex for every unique combination of position, color and normal. For a cube, you will end up with 24 vertices. While the cube has only 8 corners, there are 3 different normals at each corner, and 8 * 3 = 24. While the cube has only 6 different normals, each normal is used for 4 corners, and 6 * 4 = 24.
So define an array with 24 positions, an array with 24 colors, and an array with 24 normals, matched up to define all 24 vertices. Or one array with all of these 3 attributes interleaved. Then define your index array to connect the 24 vertices with the correct triangles, and draw.
I've done a 3d cube with OPENGL library on Android, the cube works pretty but the image on to print on the cube is not displaying...
Here's the code of my Render (java class):
public class GLRenderEx implements Renderer {
private GLCube cube;
Context c;
public GLRenderEx(Context c) {
cube = new GLCube();
this.c = c;
}
#Override
public void onDrawFrame(GL10 gl) {
gl.glDisable(GL10.GL_DITHER);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, 0, 0, -3, 0, 0, 0, 0, 2, 0);
long time = SystemClock.uptimeMillis() % 4000L;
float angle = .090f * ((int) time);
gl.glRotatef(angle, 2, 4, 3);
cube.draw(gl);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
gl.glViewport(0, 0, width, height);
float ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 25);
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig egl) {
gl.glDisable(GL10.GL_DITHER);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glClearColor(0f, 0f, 0f, 1);
gl.glClearDepthf(1f);
}
}
Here's the code of my cube:
public class GLCube {
/** The buffer holding the vertices */
private FloatBuffer vertexBuffer;
/** The buffer holding the texture coordinates */
private FloatBuffer textureBuffer;
/** The buffer holding the indices */
private ByteBuffer indexBuffer;
/** Our texture pointer */
private int[] textures = new int[1];
/**
* The initial vertex definition
*
* Note that each face is defined, even if indices are available, because of
* the texturing we want to achieve
*/
private float vertices[] = {
// Vertices according to faces
-1.0f,
-1.0f,
1.0f, // Vertex 0
1.0f,
-1.0f,
1.0f, // v1
-1.0f,
1.0f,
1.0f, // v2
1.0f,
1.0f,
1.0f, // v3
1.0f,
-1.0f,
1.0f, // ...
1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
1.0f, 1.0f,
-1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f,
1.0f, -1.0f, };
/** The initial texture coordinates (u, v) */
private float texture[] = {
// Mapping coordinates for the vertices
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
};
/** The initial indices definition */
private byte indices[] = {
// Faces definition
0, 1, 3, 0, 3,
2, // Face front
4, 5, 7, 4, 7,
6, // Face right
8, 9, 11, 8, 11,
10, // ...
12, 13, 15, 12, 15, 14, 16, 17, 19, 16, 19, 18, 20, 21, 23, 20, 23,
22, };
/**
* The Cube constructor.
*
* Initiate the buffers.
*/
public GLCube() {
//
ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuf.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
//
byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
//
indexBuffer = ByteBuffer.allocateDirect(indices.length);
indexBuffer.put(indices);
indexBuffer.position(0);
}
/**
* The object own drawing function. Called from the renderer to redraw this
* instance with possible changes in values.
*
* #param gl
* - The GL Context
*/
public void draw(GL10 gl) {
// Bind our only previously generated texture in this case
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glEnable(GL10.GL_TEXTURE_2D);
// 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_CCW);
// Enable the vertex and texture state
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
// Draw the vertices as triangles, based on the Index Buffer information
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
GL10.GL_UNSIGNED_BYTE, indexBuffer);
// Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
/**
* Load the textures
*
* #param gl
* - The GL Context
* #param context
* - The Activity context
*/
public void loadGLTexture(GL10 gl, Context context) {
// Get the texture from the Android resource directory
InputStream is = context.getResources().openRawResource(
R.drawable.ic_launcher);
Bitmap bitmap = null;
try {
// BitmapFactory is an Android graphics utility for images
bitmap = BitmapFactory.decodeStream(is);
} finally {
// Always clear and close
try {
is.close();
is = null;
} catch (IOException e) {
}
}
// 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);
// Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_CLAMP_TO_EDGE);
// Use the 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();
}
}
Why is the bitmap on my code not displaying in the cube??!!
Thanks.
I have looked through your code and haven't found a place, where you call loadGLTexture(). When I implemented your code to make textures, I just added cube.loadGLTexture(gl, c); above cube.draw(gl); in onDrawFrame() method. Hope that helps.
If you want to texture your objects, you must enable texturing with glEnable(GL_TEXTURE_2D);
I don't see this anywhere in your code.
I've had the some problem as you.
What caused my problem was the texture not matching exactly with the cube.
Check your code carefully, you might notice some mismatching.
I am workiong on the Android platform. I have just started with OpenGL and am trying to put an image on a rectangle. This is my code:
public class IntroActivity extends Activity {
private GLSurfaceView glsv = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
glsv = new GLSurfaceView(this);
glsv.setRenderer(new IntroRenderer());
setContentView(glsv);
}
#Override
protected void onResume() {
// Ideally a game should implement onResume() and onPause()
// to take appropriate action when the activity looses focus
super.onResume();
glsv.onResume();
}
#Override
protected void onPause() {
// Ideally a game should implement onResume() and onPause()
// to take appropriate action when the activity looses focus
super.onPause();
glsv.onPause();
}
Here IntroRenderer is an inner class.
class IntroRenderer implements GLSurfaceView.Renderer{
#Override
public void onDrawFrame(GL10 gl) {
gl.glClearColor(0,1.0f,1.0f,1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
float positions[] = {
0.0f,1.0f,0.0f,
0.0f, 0.0f, 0.0f,
1.0f,1.0f,0.0f,
0.0f,0.0f,0.0f,
1.0f,1.0f, 0.0f,
1.0f,0.0f,0.0f
};
ByteBuffer bb = ByteBuffer.allocateDirect(positions.length*4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer fb = bb.asFloatBuffer();
fb.put(positions);
fb.position(0);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3,GL10.GL_FLOAT, 0, fb);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3*2);
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.rect2985);
Bitmap bmp256 = Bitmap.createScaledBitmap(bmp, 256,256,false);
gl.glEnable(GL10.GL_TEXTURE_2D);
int[] buffers = new int[1];
gl.glGenTextures(1,buffers,0);
int texture = buffers[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,bmp256,0);
//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_NEAREST);
bmp.recycle();
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
}
}
}
On running this activity, the background rectangle is rendered but ther eis no image. What am I doing wrong?
I modified your renderer a bit:
class IntroRenderer implements GLSurfaceView.Renderer {
private boolean textureReady = false;
public void onDrawFrame(GL10 gl) {
if (!this.textureReady) {
this.prepareTexture(gl); // only initialize once
}
gl.glClearColor(0, 0.4f, 0.4f, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
float positions[] = {
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, 0.0f, 0.0f };
float texCoords[] = { // define texture coordinates
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 1.0f,
1.0f, 0.0f };
ByteBuffer bb = ByteBuffer.allocateDirect(positions.length * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer fb = bb.asFloatBuffer();
fb.put(positions);
fb.position(0);
// create buffer for texture coordinates
ByteBuffer texCoordByteBuffer = ByteBuffer.allocateDirect(texCoords.length * 4);
texCoordByteBuffer.order(ByteOrder.nativeOrder());
FloatBuffer texCoordBuffer = texCoordByteBuffer.asFloatBuffer();
texCoordBuffer.put(texCoords);
texCoordBuffer.position(0);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);
// enable texture buffer
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texCoordBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3 * 2);
}
private void prepareTexture(GL10 gl) {
int[] buffers = new int[1];
gl.glGenTextures(1, buffers, 0);
int texture = buffers[0];
// enable texturing and bind texture
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
Bitmap bmp = BitmapFactory.decodeResource(IntroActivity.this.getResources(), R.drawable.rect2985);
Bitmap bmp256 = Bitmap.createScaledBitmap(bmp, 256, 256, false);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp256, 0);
// setup filters
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_NEAREST);
bmp.recycle();
this.textureReady = true;
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
}
}
I added comments at the modified parts:
You have to define texture coordinates and create a buffer (like you did for vertex positions)
Enable texturing with gl.glEnable(GL10.GL_TEXTURE_2D);
You need min/mag filters
As oren suggested you should do the initialization only once.
The texture coordinates define how the texture is mapped to your triangles. You can think of a coordinate system from 0.0 to 1.0 in x and y axis where the corners (0,0; 1,0; 1,1; 0,1) define the corners of your texture. You have to assign a texture coordinate to each vertex you define.
Maybe this can help you to understand how texture coordinates work: http://www.opengl.org/resources/code/samples/sig99/advanced99/notes/node52.html
I'm not sure why is doesn't render, but your code is inefficient.
You are loading the bitmap and binding it on EVERY frame.
You should do it only once.
Also, this link can help you with great examples with this Nehe port for Android:
Nehe Port for Android
Good luck :)
How can I move the shape? I have tried changing the float that holds all the vertices but it didnt work... Then I have tried glTranslateF, but it didnt work either. What am I doing wrong?
Here is my code:
package com.chrypthic.android.reference;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.util.Log;
public class Square
{
final int VERTEX_SIZE = (2+2) *4;
FloatBuffer vertices;
ShortBuffer indices;
Texture texture;
GL10 gl;
Context c;
int x;
int y;
int w;
int h;
public Square(GL10 gl, Context context, int x, int y, int w, int h, String imageTexture)
{
this.gl = gl;
this.c = context;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4 * VERTEX_SIZE);
byteBuffer.order(ByteOrder.nativeOrder());
vertices = byteBuffer.asFloatBuffer();
/*vertices.put(new float[]{
10.0f, 10.0f, 0.0f, 1.0f, //bl
160.0f, 10.0f, 1.0f, 1.0f, //br
160.0f, 160.0f, 1.0f, 0.0f, //tr
10.0f, 160.0f, 0.0f, 0.0f, //tl
});*/
vertices.put(new float[]{
(float)x, ((float)y+(float)h), 0.0f, 1.0f, //bl
((float)x+(float)w), ((float)y+(float)h), 1.0f, 1.0f, //br
((float)x+(float)w), (float)y, 1.0f, 0.0f, //tr
(float)x, (float)y, 0.0f, 0.0f, //tl
});
vertices.flip();
byteBuffer = ByteBuffer.allocateDirect(6 * 2);
byteBuffer.order(ByteOrder.nativeOrder());
indices = byteBuffer.asShortBuffer();
indices.put(new short[]{
0, 1, 2, 2, 3, 0
});
indices.flip();
texture = new Texture(imageTexture, c, gl);
texture.load();
}
public void draw()
{
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glEnable(GL10.GL_TEXTURE_2D);
texture.bind();
gl.glColor4f(0f, 0f, 0f, 1f);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
vertices.position(0);
gl.glVertexPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices);
vertices.position(2);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices);
gl.glDrawElements(GL10.GL_TRIANGLES, 6, GL10.GL_UNSIGNED_SHORT, indices);
}
public void update()
{
//this doesnt work. I call the method every 10 milliseconds from a thread in another class.
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glTranslatef(10, y, 0);
}
}
The problem in the source you provided was the fact that glTranslatef needs to be called before performing the draw operation. Set the matrix mode to modelview set the translation and all the drawing will be drawn at the new position.
You mention you call update from another thread, but OpenGL calls are only valid on the same thread that created the context.
Also you should read about OpenGL transformations. It takes some effort to understand so have patience.
http://glprogramming.com/red/chapter03.html