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 :)
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 am try to use EffectFactory in Android for some Image Manipulation.
I tried out the sample and it works.
Here the Sample: https://android.googlesource.com/platform/development/+/master/samples/HelloEffects/src/com/example/android/mediafx/HelloEffects.java
But how can I load an image from my smartphone?
The thing is that I don't have an ImageView here but a GLSurfaceView.
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.puppy);
which method do I have to use to get a custom bitmap?
Use this BitmapRenderer class to draw Bitmap in OpenGL
private static class BitmapRenderer implements GLSurfaceView.Renderer {
private int[] textures;
private Resources resources;
public BitmapRenderer(Resources resources) {
this.resources = resources;
}
private static final float[] VERTEX_COORDINATES = new float[] {
-1.0f, +1.0f, 0.0f,
+1.0f, +1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
+1.0f, -1.0f, 0.0f
};
private static final float[] TEXTURE_COORDINATES = new float[] {
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f
};
private static final Buffer TEXCOORD_BUFFER = ByteBuffer.allocateDirect(TEXTURE_COORDINATES.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer().put(TEXTURE_COORDINATES).rewind();
private static final Buffer VERTEX_BUFFER = ByteBuffer.allocateDirect(VERTEX_COORDINATES.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer().put(VERTEX_COORDINATES).rewind();
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
textures = new int[1];
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
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);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher), 0);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
}
#Override
public void onDrawFrame(GL10 gl) {
gl.glActiveTexture(GL10.GL_TEXTURE0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, VERTEX_BUFFER);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, TEXCOORD_BUFFER);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
}
}
Set your Bitmap as below:
glSurfaceView.setEGLContextClientVersion(1);
glSurfaceView.setRenderer(new BitmapRenderer(getResources()));
glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
Following code works perfectly on older Android versions, but only shows a black screen on newer versions (I guess 4.2 and higher).
Im very new to OpenGL and I used to work with Canvas/SurfaceView, but now I need GLSurfaceView for the performance, so I leeched some code from here and there without exactly knowing what it does. I didnt start a whole new project, I just rewrote some of my "Canvas-Code" to a GLSurfaceView loop. Thats why it might look strange and inefficient.
Explanation for the code:
The class "Sprite" contains a Bitmap, xPos and yPos. In "defineStuff();" I append a few different "Sprites" to a List and the GLSurfaceView draws everything from the List.
This is not the whole code, I removed pretty much to make it more clear.
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); //so its Fullscreen
defineStuff();
glSurfaceView = new GLSurfaceView(this);
glSurfaceView.setRenderer(new GlRenderer());
glSurfaceView.setOnTouchListener(this);
setContentView(glSurfaceView);
}
The Sprite class:
public class Sprite {
private FloatBuffer vertexBuffer; // buffer holding the vertices
private FloatBuffer textureBuffer; // buffer holding the texture coordinates
private float texture[];
private float vertices[];
public Bitmap bmp;
public boolean visible;
public String name;
public float posX;
public float posY;
public Sprite(String name, Bitmap bitmap, float posX, float posY, boolean visible) {
this.name = name;
this.visible = visible;
setBuffers(bitmap, posX, posY);
}
public void setBuffers(Bitmap bitmap, float posX, float posY) {
bmp = bitmap;
}
this.posX = posX;
this.posY = posY;
float tempVertices[] = {
posX, posY + bitmap.getHeight(), 0.0f, // V1 - bottom left
posX, posY, 0.0f, // V2 - top left
posX + bitmap.getWidth(), posY + bitmap.getHeight(), 0.0f, // V3 - bottom right
posX + bitmap.getWidth(), posY, 0.0f // V4 - top right
};
vertices = new float[tempVertices.length];
System.arraycopy(tempVertices, 0, vertices, 0, tempVertices.length);
// 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);
float tempTexture[] = {
// 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)
};
texture = new float[tempTexture.length];
System.arraycopy(tempTexture, 0, texture, 0, tempTexture.length);
byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
}
/** The texture pointer */
private int[] textures = new int[1];
public void loadGLTexture(GL10 gl) { // every Sprite has to be loaded before being drawn
// 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, bmp, 0);
}
public void draw(GL10 gl, float interpolation) {
gl.glPushMatrix();
gl.glTranslatef (speedInX * interpolation, speedInY * interpolation, 0f);
// 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);
gl.glPopMatrix();
}
}
My renderer:
public class GlRenderer implements Renderer {
#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); // move 5 units INTO the screen
// is the same as moving the camera 5 units away
updateLogic(gl); //there was very much code around this but I removed it to make it more clear
float interpolation = (float) (SystemClock.uptimeMillis() + SKIP_TICKS - nextGameTick) / SKIP_TICKS;
spriteList.toFirst();
while (spriteList.getObject() != null) {
((Sprite) spriteList.getObject()).draw(gl, interpolation);
spriteList.next();
}
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION); // or some matrix uniform if using shaders
gl.glLoadIdentity();
gl.glOrthof(0, width, height, 0, -1, 1); // this will allow to pass vertices in 'canvas pixel' coordinates
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glDisable(GL10.GL_DITHER);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glEnable(GL10.GL_TEXTURE_2D); //Enable Texture Mapping ( NEW )
gl.glShadeModel(GL10.GL_SMOOTH); //Enable Smooth Shading
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //Set Background
gl.glClearDepthf(1.0f); //Depth Buffer Setup
gl.glEnable(GL10.GL_DEPTH_TEST); //Enables Depth Testing
gl.glDepthFunc(GL10.GL_LEQUAL); //The Type Of Depth Testing To Do
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); // So alpha works, but it still doesnt work everytime :)
spriteList.toFirst();
while (spriteList.getObject() != null) {
((Sprite) spriteList.getObject()).loadGLTexture(gl);
spriteList.next();
}
}
}
brecause you have
gl.glOrthof(0,width,height,0,-1,1);
your code doesnt require depth testing, try getting rid of
| GL10.GL_DEPTH_BUFFER_BIT
gl.glClearDepthf(1.0f);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glTranslatef(0.0f, 0.0f, -5.0f);
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
I have followed a tutorial on how to display an image in OpenGL, and I first had to make a square and then texture it. I have tried gl.glColor4f(0f,0f,0f,1f); and that works, I can see the square. But then when I try to texture it, the screen just stays white. What did I do wrong?
Here is the screen with the gl.glColor4f(0f,0f,0f,1f); :
If I apply the texture (using the custom Texture class that the tutorial suggested), the screen is completely white.
Here is my code:
Square.java:
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;
public class Square
{
final int VERTEX_SIZE = (2+2) *4;
FloatBuffer vertices;
ShortBuffer indices;
Texture texture;
GL10 gl;
Context c;
public Square(GL10 gl, Context context)
{
this.gl = gl;
this.c = context;
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(VERTEX_SIZE * 4);
byteBuffer.order(ByteOrder.nativeOrder());
vertices = byteBuffer.asFloatBuffer();
vertices.put(new float[]{
10.0f, 10.0f, 0.0f, 0.0f, //bl
160.0f, 10.0f, 1.0f, 0.0f, //br
160.0f, 160.0f, 1.0f, 1.0f, //tr
10.0f, 160.0f, 1.0f, 0.0f, //tl
});
vertices.flip();
byteBuffer = ByteBuffer.allocateDirect(VERTEX_SIZE * 4);
byteBuffer.order(ByteOrder.nativeOrder());
indices = byteBuffer.asShortBuffer();
indices.put(new short[]{
0, 1, 2, 2, 3, 0
});
indices.flip();
texture = new Texture("image/picture.png", c, gl);
}
public void draw()
{
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);
}
}
Texture.java
package com.chrypthic.android.reference;
import java.io.InputStream;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
public class Texture {
String texturePath;
Context context;
GL10 gl;
int textureId;
int minFilter;
int magFilter;
Bitmap texture;
public Texture(String texturePath, Context context, GL10 gl)
{
this.gl = gl;
this.texturePath = texturePath;
this.context = context;
}
public void load()
{
try{
AssetManager assetManager = context.getAssets();
InputStream is = assetManager.open(texturePath);
texture = BitmapFactory.decodeStream(is);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, texture, 0);
setFilters(GL10.GL_NEAREST, GL10.GL_NEAREST);
gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
}catch(Exception e)
{
e.printStackTrace();
}
}
public void reload()
{
load();
bind();
setFilters(minFilter, magFilter);
gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
}
public void setFilters(int minFilter, int magFilter)
{
this.minFilter = minFilter;
this.magFilter = magFilter;
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, minFilter);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, magFilter);
}
public void bind()
{
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
}
public void dispose()
{
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
int[] textureIds = {textureId};
gl.glDeleteTextures(1, textureIds, 0);
}
}
OpenGLRenderer.java
package com.chrypthic.android.reference;
import java.util.Random;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;
public class OpenGLRenderer implements Renderer
{
Random rand = new Random();
int mWidth = 0;
int mHeight = 0;
Context c;
Square square;
public OpenGLRenderer(Context c)
{
this.c = c;
}
#Override
public void onDrawFrame(GL10 gl)
{
gl.glClearColor(1, 1, 1, 1);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glViewport(0, 0, mWidth, mHeight);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrthof(0, mWidth, 0, mHeight, -1, 1);
if(square != null)square.draw();
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
mWidth = width;
mHeight = height;
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
square = new Square(gl, c);
}
}
I hope you can help me, if you need even more information just tell me.
Thanks in advance. I did't post the white screen as a screenshot, because it seems kind of pointless with the white background that stackoverflow have.
You never create the texture!
public void load()
{
try{
int []texture = new int[1];
gl.glGenTextures(1, texture,0);//the missing method
textureId = texture[0];
//now you can call
AssetManager assetManager = context.getAssets();
InputStream is = assetManager.open(texturePath);
texture = BitmapFactory.decodeStream(is);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);/*this fails
if textureId is a 'random' number. You must/should generate a valid id. */
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, texture, 0);
setFilters(GL10.GL_NEAREST, GL10.GL_NEAREST);
gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
It is exactly the opposite of your dispose() method.
Going from a comment to an answer.
(Comment): Why are you using glVertexPointer twice rather that glVertexPointer and then glTexCoordPointer? Also there seems to be a typo in that line that says GL_FLAT instead of GL_FLOAT. Are you sure you're giving us your actual code?
-Answer starts here-
It looks like you aren't using texture coordinates at all. You have to specify which corner of the texture you'd like to assign to which corner of the triangle/quad. For example, I see that you've got a "tl" comment next to the top left vertex. You similarly need to supply a texture coordinate that says "use the top left corner of the image with this vertex" and then OpenGL figures out the rest.
Then when you go to pass the vertex pointer, you also have to pass a texture coordinate pointer that contains those texture coordinates I were just talking about in the previous paragraph. You do this with glTexCoordPointer in the exact same fashion as glVertexPointer. You can also load texture coordinates into a VBO (in fact, into the same VBO as the vertices, then you can call glTexCoordPointer with the offset into the VBO to where the tex coords start).
Let me know (via comment) if you need more elaboration/code examples or more explanation anywhere.
Edit 1:
See these links for information about texture mapping:
gamedev,
nehe
Edit 2:
Okay, stupid me. I didn't notice that you've actually got the texture coordinate data in with the vertex data. Try changing your second call to glVertexPointer to glTexCoordPointer. This might fix your problem entirely.