user485498
user485498

Reputation:

Why won't this OpenGL ES code create a texture?

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?

Upvotes: 2

Views: 230

Answers (2)

micha
micha

Reputation: 49542

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

Upvotes: 2

Oren Bengigi
Oren Bengigi

Reputation: 1034

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 :)

Upvotes: 0

Related Questions