Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
New Contributor
Posts: 8
Registered: ‎03-10-2010
My Device: 9550
My Carrier: Verizon
Accepted Solution

OpenGl Textures

Hi,  I'm having trouble with displaying textures in openGL.  It's got to be something stupid like an option I forgot.  I've done opengl on the iphone and on android.  Really trying to figure out what I've forgotten.  The code is based off the blackberry example: http://docs.blackberry.com/en/developers/deliverables/11942/CS_OpenGLTest_952941_11.jsp

 

 

I took it and have been trying to load a texture onto the polygon instead of the colors.  I can't see anything, not even a bunch of color fuzz. help please.  code below:

 

 

public class OpenGLTestScreen extends FullScreen implements Runnable {

    private EGL11 _egl;

    private EGLDisplay _eglDisplay;

    private EGLConfig _eglConfig;

    private EGLSurface _eglSurface;

    private EGLContext _eglContext;

    private GL10 _gl;

 

    private Bitmap _offscreenBitmap;

    private Graphics _offscreenGraphics;

 

    private FloatBuffer _vertexArray;

    private FloatBuffer _colorArray;

    private FloatBuffer mTextureBuffer;

 

    private boolean _running;

    private boolean _paused;

 

    private int textureId;

 

    OpenGLTestScreen()

    {

        super(FullScreen.DEFAULT_MENU | FullScreen.DEFAULT_CLOSE);

    }

 

    private void initialize()

    {

        // Get EGL interface

        _egl = (EGL11)EGLContext.getEGL();

 

        // Get the EGL display

        _eglDisplay = _egl.eglGetDisplay(EGL11.EGL_DEFAULT_DISPLAY);

 

        // Initialize the display for EGL, null since we dont really need the version

        _egl.eglInitialize(_eglDisplay, null);

 

        // Choose an EGL config

        EGLConfig[] configs = new EGLConfig[1];

        int[] numConfigs = new int[1];

        int[] attrs =

        {

            EGL11.EGL_RED_SIZE,   5,

            EGL11.EGL_GREEN_SIZE, 6,

            EGL11.EGL_BLUE_SIZE,  5,

            EGL11.EGL_NONE

        };

        _egl.eglChooseConfig(_eglDisplay, attrs, configs, 1, numConfigs);

        _eglConfig = configs[0];

 

        // Create an EGL window surface

        _eglSurface = _egl.eglCreateWindowSurface

            (_eglDisplay, _eglConfig, this, null);

 

        // Create an EGL context

        createEGLContext();

 

        float[] vertices =

        {

            -0.5f, -0.5f, 0.0f,

            0.5f, -0.5f, 0.0f,

            -0.5f, 0.5f, 0.0f,

            0.5f, 0.5f, 0.0f

        };

        float[] colors =

        {

            0.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

        };

        _vertexArray = ByteBuffer.allocateDirect(vertices.length * 4).asFloatBuffer();

        _vertexArray.put(vertices);

        _vertexArray.rewind();

        _colorArray = ByteBuffer.allocateDirect(colors.length * 4).asFloatBuffer();

        _colorArray.put(colors);

        _colorArray.rewind();

 

        _gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

        _gl.glEnable(GL11.GL_TEXTURE_2D);

        _gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        _gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        _gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);

        _gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

        _gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);

        _gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);

        _gl.glPixelStorei(GL10.GL_UNPACK_ALIGNMENT, 1);

        _gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);

        _gl.glEnable(GL10.GL_BLEND);

        //_gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE_MINUS_SRC_ALPHA);

 

        _gl.glShadeModel( GL10.GL_FLAT );

        _gl.glBlendFunc( GL10.GL_ONE, GL10.GL_ONE );

        _gl.glHint( GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST );

        _gl.glShadeModel(GL10.GL_SMOOTH);

 

        Bitmap colormap = Bitmap.getBitmapResource("ap.png");

 

        IntBuffer m_id = ByteBuffer.allocateDirect(10).asIntBuffer();

        _gl.glGenTextures(1, m_id);

        m_id.rewind();

        textureId = m_id.get();

 

        _gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);

 

        GLUtils.glTexImage2D(_gl, GL10.GL_TEXTURE_2D, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, colormap, null);

        colormap = null;

 

     float texCoords[] = {

     0, _1.0f, 

     _1.0f, _1.0f, 

     0, 0, 

     _1.0f, 0

     };

 

   ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4);

   mTextureBuffer = tbb.asFloatBuffer();

   mTextureBuffer.put(texCoords);

 

   mTextureBuffer.rewind();

   _gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);

 

    }

 

    private void createEGLContext()

    {

        // Create an EGL context

        _eglContext = _egl.eglCreateContext

            (_eglDisplay, _eglConfig, EGL10.EGL_NO_CONTEXT, null);

 

        // Get the GL interface for our new context

        _gl = (GL10)_eglContext.getGL();

 

        // Make our new context current

        _egl.eglMakeCurrent

           (_eglDisplay, _eglSurface, _eglSurface, _eglContext);

    }

 

    private void destroyEGL()

    {

        _egl.eglMakeCurrent(_eglDisplay, EGL10.EGL_NO_SURFACE,

            EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);

        _egl.eglDestroyContext(_eglDisplay, _eglContext);

        _egl.eglDestroySurface(_eglDisplay, _eglSurface);

    }

 

    private void handleContextLost()

    {

        // Destroy our EGL context

        _egl.eglMakeCurrent(_eglDisplay, EGL10.EGL_NO_SURFACE,

            EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);

        _egl.eglDestroyContext(_eglDisplay, _eglContext);

        _eglContext = EGL10.EGL_NO_CONTEXT;

 

        // Re-create our EGL context

        createEGLContext();

    }

 

    /**

     * Main render loop.

     */

    public void run()

    {

        initialize();

 

        while (_running)

        {

            // Idle If we are in the background

            if (_paused)

            {

                synchronized (this)

                {

                    try

                    {

                        wait();

                    }

                    catch (InterruptedException x) { }

                }

            }

 

            updateBackBuffer();

 

            renderFrame();

 

            // Throttle cpu usage

            try

            {

                Thread.sleep(20);

            }

            catch (InterruptedException x) { }

        }

 

        destroyEGL();

    }

 

    private void renderFrame()

    {

        // Make our context and surface current and check for EGL_CONTEXT_LOST

        if (!_egl.eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _eglContext))

        {

            if (_egl.eglGetError() == EGL11.EGL_CONTEXT_LOST)

                handleContextLost();

        }

 

        // Signal that we are about to begin OpenGL rendering

        _egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, _offscreenGraphics);

 

        render(_gl);

 

        // Signal that OpenGL ES rendering is complete

        _egl.eglWaitGL();

 

        // Swap the window surface to the display

        _egl.eglSwapBuffers(_eglDisplay, _eglSurface);

    }

 

    private void render(GL10 gl)

    {

        // Set our GL viewport

        gl.glViewport(0, 0, getWidth(), getHeight());

 

        // Clear the surface

        gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

 

        // Set our projection matrix

        gl.glMatrixMode(GL10.GL_PROJECTION);

        gl.glLoadIdentity();

        GLUtils.gluPerspective

            (gl, 45.0f, (float)getWidth()/(float)getHeight(), 0.15f, 10.0f);

 

        // Draw our triangle

        gl.glMatrixMode(GL10.GL_MODELVIEW);

        gl.glLoadIdentity();

        gl.glTranslatef(0.0f, 0.0f, -3.0f);

 

        gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);

        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexArray);

        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);

 

        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);

 

        //gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);

    }

 

    /**

     * Called by the UI system to paint the screen.

     */

    protected void paint(Graphics g)

    {

        if (_offscreenBitmap != null)

            g.drawBitmap(0, 0, _offscreenBitmap.getWidth(),

                _offscreenBitmap.getHeight(), _offscreenBitmap, 0, 0);

    }

 

    /**

     * Called when the visibility of our screen changes.

     *

     * @param visible true if our screen is being made visible,

     * false if it's being hidden

     */

    protected void onVisibilityChange(boolean visible)

    {

        if (visible)

        {

            resume();

        }

        else

        {

            pause();

        }

    }

 

    /**

     * Called when the screen is closing.

     */

    public void close()

    {

        _running = false;

        synchronized (this) { notifyAll(); }

 

        super.close();

    }

 

    /**

     * Keeps the back buffer in sync with the screen size.

     */

    private void updateBackBuffer()

    {

        if (_offscreenBitmap != null)

        {

            if (_offscreenBitmap.getWidth() == getWidth() &&

                _offscreenBitmap.getHeight() == getHeight())

                return; // no change needed

        }

 

        _offscreenBitmap = new Bitmap(getWidth(), getHeight());

        _offscreenGraphics = Graphics.create(_offscreenBitmap);

    }

 

    private void pause()

    {

        _paused = true;

    }

 

    private void resume()

    {

        if (_running)

        {

            // Pause the render loop

            _paused = false;

            synchronized (this) { notifyAll(); }

        }

        else

        {

            // Start the render thread.

            _running = true;

            new Thread(this).start();

        }

    }

}

 

New Contributor
Posts: 8
Registered: ‎03-10-2010
My Device: 9550
My Carrier: Verizon

Re: OpenGl Textures

I'm pretty sure it's gotta be in

 

initialize()

 

or

 

render(GL10 gl).

Developer
Posts: 1,805
Registered: ‎04-28-2009
My Device: Z10 (STL100-4)-10.2.1.3253, Z10 (STL100-3)-10.3.1.997 Dev OS, Z30 (STA100-5)-10.3.1.997 Dev OS, Passport (SQW100-1)-10.3.0.1418, PlayBook (16GB)-2.1.0.1917
My Carrier: Verizon

Re: OpenGl Textures

I have a working app that uses textures so I am taking these ideas from that, don't know how big of a difference it might actually make.

 

OpenGL ES is state based so you should enable the use of textures by calling:

//Enable
gl.glEnable(GL10.GL_TEXTURE_2D);

//Drawing Code...

//Disable
gl.glDisable(GL10.GL_TEXTURE_2D);

 

In my app I call "glBindTexture" in the "Drawing Code" area from above follwed by "glTexImage2D" (I use the OpenGL function not the GLUtils because I don't know if it references the Bitmap or if it does a convertion to Buffer then returns).

 

Also though I don't know how big of an issue it might be, if any issue at all, but if your texture doesn't have Alpha then saying it is ARGB might cause issues.

---Spends time in #blackberrydev on freenode (IRC)----
Three simple rules:
1. Please use the search bar before making new posts.
2. "Like" posts that you find helpful.
3. If a solution has been found for your post, mark it as solved.
--I code too much. Well, too bad.
New Contributor
Posts: 8
Registered: ‎03-10-2010
My Device: 9550
My Carrier: Verizon

Re: OpenGl Textures

Am I generating and binding the texture right with:

 

Bitmap colormap = Bitmap.getBitmapResource("ap.png");

 

        IntBuffer m_id = ByteBuffer.allocateDirect(10).asIntBuffer();

        _gl.glGenTextures(1, m_id);

        m_id.rewind();

        textureId = m_id.get();

 

        _gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);

 

        GLUtils.glTexImage2D(_gl, GL10.GL_TEXTURE_2D, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, colormap, null);

        colormap = null;

 

 

Is there anyway you could post some code of the way you do it?

 

I also have tried using:

 

gl.glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, Buffer pixels)

 

Does the texture HAVE to be power of 2?  That's what I'm using right now just to get the base case, but you should be able to load a non-power of 2 texture, just have to adjust how it's rendered right?

 

Do I need to keep the Bitmap in memory?

 

What about using: glCopyTexImage2D(int target, int level, int internalformat, int x, int y, int width, int height, int border) 

 

 

I've tried most of the stuff mentioned.  I was just wondering if any of it might ring any bells.  I might not have tried it properly.  Eg. might have specified wrong parameters.

 

Thanks.

 

New Contributor
Posts: 8
Registered: ‎03-10-2010
My Device: 9550
My Carrier: Verizon

Re: OpenGl Textures

[ Edited ]

Ok, So I figured out the problem.  But not necessarily how to fix it.  It's in how the EGLConfig is created.  It's being created to bind rgb565 pixels.  I found this out when I used Bitmap.getRGB565 instead of Bitmap.getARGB to extract the pixels.  The texture's colors are all screwed up, but I can see them, and I'm not getting an OutOfMemory Exception which I sometimes got.  Now all I have to do is figure out how to redo the EGLConfig.

 

Any help?

 

I've tried different parameters, but to no avail (will continue trying).  Below is what I have that gets the rgb565 to show up:

 

 

        // Choose an EGL config
        EGLConfig[] configs = new EGLConfig[1];
        int[] numConfigs = new int[1];
        int[] attrs =
        {
                EGL11.EGL_RED_SIZE,   5,
                EGL11.EGL_GREEN_SIZE, 6,
                EGL11.EGL_BLUE_SIZE,  5,
                EGL11.EGL_NONE
        };
        _egl.eglChooseConfig(_eglDisplay, attrs, configs, 1, numConfigs);
        _eglConfig = configs[0];
        // Create an EGL window surface
        _eglSurface = _egl.eglCreateWindowSurface
            (_eglDisplay, _eglConfig, this, null);
        // Create an EGL context
        createEGLContext();
New Contributor
Posts: 8
Registered: ‎03-10-2010
My Device: 9550
My Carrier: Verizon

Re: OpenGl Textures

Turns out it wasn't the config's problem.  It was the way I was extracting the bits.  OpenGL 1.0 accepts RGBA  whereas the Bitmap was reading the images in as ARGB.  I used a conversion function from:

 

http://potatoland.org/code/gl/source/glapp/GLImage.java

 

Below are the functions if you want them by themselves.

 

 

 

    public static ByteBuffer convertImagePixelsRGBA(int[] jpixels, int imgw, int imgh, boolean flipVertically) {
        byte[] bytes;     // will hold pixels as RGBA bytes
        if (flipVertically) {
            jpixels = flipPixels(jpixels, imgw, imgh); // flip Y axis
        }
        bytes = convertARGBtoRGBA(jpixels);
        return allocBytes(bytes);  // convert to ByteBuffer and return
    }
    /**
     * Convert pixels from java default ARGB int format to byte array in RGBA format.
     * @param jpixels
     * @return
     */
    public static byte[] convertARGBtoRGBA(int[] jpixels)
    {
        byte[] bytes = new byte[jpixels.length*4];  // will hold pixels as RGBA bytes
        int p, r, g, b, a;
        int j=0;
        for (int i = 0; i < jpixels.length; i++) {
            p = jpixels[i];
            a = (p >> 24) & 0xFF;  // get pixel bytes in ARGB order
            r = (p >> 16) & 0xFF;
            g = (p >> 8) & 0xFF;
            b = (p >> 0) & 0xFF;
            bytes[j+0] = (byte)r;  // fill in bytes in RGBA order
            bytes[j+1] = (byte)g;
            bytes[j+2] = (byte)b;
            bytes[j+3] = (byte)a;
            j += 4;
        }
        return bytes;
    }
    public static int[] flipPixels(int[] imgPixels, int imgw, int imgh)
    {
        int[] flippedPixels = null;
        if (imgPixels != null) {
            flippedPixels = new int[imgw * imgh];
            for (int y = 0; y < imgh; y++) {
                for (int x = 0; x < imgw; x++) {
                    flippedPixels[ ( (imgh - y - 1) * imgw) + x] = imgPixels[ (y * imgw) + x];
                }
            }
        }
        return flippedPixels;
    }
    
    public static ByteBuffer allocBytes(byte[] bytearray) {
        ByteBuffer bb = ByteBuffer.allocateDirect(bytearray.length);
        bb.put(bytearray).flip();
        return bb;
    }

 

New Contributor
Posts: 8
Registered: ‎03-10-2010
My Device: 9550
My Carrier: Verizon

Re: OpenGl Textures

Ok,  So here are the things I've learned.

 

1. The texture doesn't bind right unless I have those 2 texture parameters after the bind

 

gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); 
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

 

 

2. This method is awesome and makes it so you don't have to do any crazy pixel conversion (though you still have to do some texture coordinate tweaking for the power of 2 scaling.

 

GLUtils.glTexImage2D(gl, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bmp, null);

 

 

3. If you want alpha enabled in your gl configuration you have to configure it like this:

 

 

        EGLConfig[] configs = new EGLConfig[1];

        int[] numConfigs = new int[1];

        int[] attrs =

        {

                EGL11.EGL_RED_SIZE,   8,

                EGL11.EGL_GREEN_SIZE, 8,

                EGL11.EGL_BLUE_SIZE,  8,

                EGL11.EGL_ALPHA_SIZE,  8,

                EGL11.EGL_NONE

        };

        _egl.eglChooseConfig(_eglDisplay, attrs, configs, 1, numConfigs);

        _eglConfig = configs[0];

 

 

 

Hopefully this helps some poor soul in the future whose trying to use opengl on blackberry.

Developer
Posts: 1,805
Registered: ‎04-28-2009
My Device: Z10 (STL100-4)-10.2.1.3253, Z10 (STL100-3)-10.3.1.997 Dev OS, Z30 (STA100-5)-10.3.1.997 Dev OS, Passport (SQW100-1)-10.3.0.1418, PlayBook (16GB)-2.1.0.1917
My Carrier: Verizon

Re: OpenGl Textures

Thank you, that information should be helpful for those who can't find "good" information on OpenGL ES.

---Spends time in #blackberrydev on freenode (IRC)----
Three simple rules:
1. Please use the search bar before making new posts.
2. "Like" posts that you find helpful.
3. If a solution has been found for your post, mark it as solved.
--I code too much. Well, too bad.
Contributor
Posts: 20
Registered: ‎11-15-2010
My Device: Not Specified

Re: OpenGl Textures

This is helpful, but can you load an image in A8R8G8B8 using net.rim.device.api.system.Bitmap? Bitmap seems to want to load in RGB 565, completely ignoring the alpha channel. How do you load the alpha channel from a PNG on BB then? What library do you use?

Developer
Posts: 1,805
Registered: ‎04-28-2009
My Device: Z10 (STL100-4)-10.2.1.3253, Z10 (STL100-3)-10.3.1.997 Dev OS, Z30 (STA100-5)-10.3.1.997 Dev OS, Passport (SQW100-1)-10.3.0.1418, PlayBook (16GB)-2.1.0.1917
My Carrier: Verizon

Re: OpenGl Textures

The alpha channel is a seperate "layer" so as long as you specifiy that you want alpha it will get used, otherwise it will not.

---Spends time in #blackberrydev on freenode (IRC)----
Three simple rules:
1. Please use the search bar before making new posts.
2. "Like" posts that you find helpful.
3. If a solution has been found for your post, mark it as solved.
--I code too much. Well, too bad.