OpenGL -- repetitive loading of textures

Tutorials concerning the OpenGL® ES cross-platform API for full-function 2D and 3D graphics on the Google-Android platform.

OpenGL -- repetitive loading of textures

Postby mlegris » Tue Feb 02, 2010 6:07 pm

Hi,

I am not new to programming (10+ years) but certainly new to OpenGL. I am trying to create a FPS meter that will display itself in a GLSurfaceView .. so in the Renderer I created a function to calculare FPS..

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. // member variable
  3.  
  4. private List<Long> _stamps;
  5.  
  6.  
  7.  
  8. // in constructor
  9.  
  10. public StaticTriangleRenderer(Context context)
  11.  
  12. {
  13.  
  14.         // snipped code
  15.  
  16.         _stamps = new ArrayList<Long>();
  17.  
  18. }
  19.  
  20.  
  21.  
  22. // function to calculate fps, called on each onDrawFrame
  23.  
  24. private int calculateFps()
  25.  
  26. {
  27.  
  28.         long now = new Date().getTime();               
  29.  
  30.         _stamps.add(now);
  31.  
  32.         now -= 1000;
  33.  
  34.         long stamp = _stamps.get(0);
  35.  
  36.         while(stamp < now)
  37.  
  38.         {
  39.  
  40.                 _stamps.remove(0);
  41.  
  42.                 stamp = _stamps.get(0);
  43.  
  44.         }
  45.  
  46.        
  47.  
  48.         return _stamps.size();
  49.  
  50. }
  51.  
  52.  
  53.  
  54. // function to generate fps output "texture"
  55.  
  56. protected Bitmap createFPSBitmap()
  57.  
  58. {
  59.  
  60.         Bitmap bmp = Bitmap.createBitmap(128, 128, Config.ARGB_4444); // Config.ARGB_4444);
  61.  
  62.         Canvas canvas = new Canvas(bmp);
  63.  
  64.         Paint paint = new Paint();
  65.  
  66.         paint.setColor(0xFFFFFFFF);
  67.  
  68.         paint.setTextSize(32);
  69.  
  70.         canvas.drawText("" + calculateFps()+ " fps", 0, 16, paint);
  71.  
  72.        
  73.  
  74.         return bmp;
  75.  
  76. }
  77.  
  78.  
Parsed in 0.034 seconds, using GeSHi 1.0.8.4


Now, I tried to reassign the texture using GLUtils.texImage2D in onDrawFrame, I understand this is far from a best practice but it would help me a lot if I could understand why it crashes after the second time.. I ended up doing the following inside of onSurfaceCreated. I copied the full code below so you can see the whole context..

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public void onSurfaceCreated(GL10 gl, EGLConfig config)
  3.  
  4. {
  5.  
  6.     /*
  7.  
  8.      * By default, OpenGL enables features that improve quality
  9.  
  10.      * but reduce performance. One might want to tweak that
  11.  
  12.      * especially on software renderer.
  13.  
  14.      */
  15.  
  16.     glDisable(GL_DITHER);
  17.  
  18.  
  19.  
  20.     /*
  21.  
  22.      * Some one-time OpenGL initialization can be made here
  23.  
  24.      * probably based on features of this particular context
  25.  
  26.      */
  27.  
  28.     glHint(GL_PERSPECTIVE_CORRECTION_HINT,
  29.  
  30.             GL_FASTEST);
  31.  
  32.  
  33.  
  34.     glClearColor(.5f, .5f, .5f, 1);
  35.  
  36.     glShadeModel(GL_SMOOTH);
  37.  
  38.     glEnable(GL_DEPTH_TEST);
  39.  
  40.     glEnable(GL_TEXTURE_2D);
  41.  
  42.  
  43.  
  44.     /*
  45.  
  46.      * Create our texture. This has to be done each time the
  47.  
  48.      * surface is created.
  49.  
  50.      */
  51.  
  52.  
  53.  
  54.     int[] textures = new int[1];
  55.  
  56.     glGenTextures(1, textures, 0);
  57.  
  58.  
  59.  
  60.     mTextureID = textures[0];
  61.  
  62.     glBindTexture(GL_TEXTURE_2D, mTextureID);
  63.  
  64.  
  65.  
  66.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  67.  
  68.             GL_NEAREST);
  69.  
  70.     glTexParameterf(GL_TEXTURE_2D,
  71.  
  72.             GL_TEXTURE_MAG_FILTER,
  73.  
  74.             GL_LINEAR);
  75.  
  76.  
  77.  
  78.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
  79.  
  80.             GL_CLAMP_TO_EDGE);
  81.  
  82.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
  83.  
  84.             GL_CLAMP_TO_EDGE);
  85.  
  86.  
  87.  
  88.     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
  89.  
  90.             GL_REPLACE);
  91.  
  92.  
  93.  
  94.  
Parsed in 0.034 seconds, using GeSHi 1.0.8.4

This is where the faulty code starts..
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.    
  3.  
  4.     Log.i("Renderer", "1st texture assignment");
  5.  
  6.     Bitmap bmp = createFPSBitmap();
  7.  
  8.     GLUtils.texImage2D(GL_TEXTURE_2D, 0, createFPSBitmap(), 0);
  9.  
  10.     bmp.recycle();
  11.  
  12.    
  13.  
  14.     // clean up after, not sure this is necessary
  15.  
  16.     glDeleteTextures(1, textures, 0);
  17.  
  18.     glGenTextures(1, textures, 0);
  19.  
  20.     glBindTexture(GL_TEXTURE_2D, mTextureID);
  21.  
  22.  
  23.  
  24.     Log.i("Renderer", "2nd texture assignment");
  25.  
  26.     bmp = createFPSBitmap();
  27.  
  28.     GLUtils.texImage2D(GL_TEXTURE_2D, 0, bmp, 0);
  29.  
  30.     bmp.recycle();
  31.  
  32.     Log.i("Renderer", "textureId i:"+textures[0]);
  33.  
  34.    
  35.  
  36.    
  37.  
  38.     Log.i("Renderer", "3rd texture assignment");
  39.  
  40.     bmp = createFPSBitmap();
  41.  
  42.     GLUtils.texImage2D(GL_TEXTURE_2D, 0, createFPSBitmap(), 0);
  43.  
  44.     bmp.recycle();
  45.  
  46.    
  47.  
  48.     glDeleteTextures(1, textures, 0);
  49.  
  50.     glGenTextures(1, textures, 0);
  51.  
  52.     glBindTexture(GL_TEXTURE_2D, mTextureID);
  53.  
  54.  
  55.  
  56.  
  57.  
  58.     Log.i("Renderer", "4th");
  59.  
  60.     bmp = createFPSBitmap();
  61.  
  62.     GLUtils.texImage2D(GL_TEXTURE_2D, 0, createFPSBitmap(), 0);
  63.  
  64.     bmp.recycle();
  65.  
  66.    
  67.  
  68.     glDeleteTextures(1, textures, 0);
  69.  
  70.     glGenTextures(1, textures, 0);
  71.  
  72.     glBindTexture(GL_TEXTURE_2D, mTextureID);
  73.  
  74.     Log.i("Renderer", "5th");
  75.  
  76.     bmp = createFPSBitmap();
  77.  
  78.     GLUtils.texImage2D(GL_TEXTURE_2D, 0, createFPSBitmap(), 0);
  79.  
  80.     bmp.recycle();
  81.  
  82.    
  83.  
  84.     glDeleteTextures(1, textures, 0);
  85.  
  86.     glGenTextures(1, textures, 0);
  87.  
  88.     glBindTexture(GL_TEXTURE_2D, mTextureID);        
  89.  
  90.     Log.i("Renderer", "6th");
  91.  
  92.     bmp = createFPSBitmap();
  93.  
  94.     GLUtils.texImage2D(GL_TEXTURE_2D, 0, createFPSBitmap(), 0);
  95.  
  96.     bmp.recycle();
  97.  
  98.    
  99.  
  100.     glDeleteTextures(1, textures, 0);
  101.  
  102.     glGenTextures(1, textures, 0);
  103.  
  104.     glBindTexture(GL_TEXTURE_2D, mTextureID);        
  105.  
  106.     Log.i("Renderer", "7th");
  107.  
  108.     bmp = createFPSBitmap();
  109.  
  110.     GLUtils.texImage2D(GL_TEXTURE_2D, 0, createFPSBitmap(), 0);
  111.  
  112.     bmp.recycle(); */
  113.  
  114.    
  115.  
  116.     Log.i("Renderer", "done with textures");
  117.  
  118. }
  119.  
  120.  
Parsed in 0.042 seconds, using GeSHi 1.0.8.4


For some reason it works twice, then crashes. What am I doing wrong?

Ultimately I don't want to do this in onSurfaceCreated, I want to update the texture inside of onDrawFrame so I can update the FPS meter texture to draw it on a square.

Also I tried the sample in APIDemos called "SpriteText" and it throws runtime errors.. weird.

I am testing everything on the Nexus One.

Thanks

Martin
mlegris
Freshman
Freshman
 
Posts: 2
Joined: Mon Feb 01, 2010 10:48 pm
Location: Montreal, QC

Top

Postby MichaelEGR » Tue Feb 02, 2010 9:07 pm

I unfortunately don't have time to look at the code you posted, but I'd recommend working with text directly in OpenGL such that you create one texture with all the letters to be used packed into it and index where they are then create a utility method to take a string or array of chars and then draw directly in GL after binding that one texture. You absolutely don't want to create an Bitmap per frame and upload it to GL as that is very inefficient. You can create this texture dynamically such that you can choose the size and particular Android font.

Search "opengl font rendering"; there are many ways to get text/fonts into GL.

If it is any consolation I'm releasing a library/framework that does the above, but it's not due out for another month.
Founder & Principal Architect; EGR Software LLC
http://www.typhonrt.org
http://www.egrsoftware.com
User avatar
MichaelEGR
Senior Developer
Senior Developer
 
Posts: 147
Joined: Thu Jan 21, 2010 5:30 am
Location: San Francisco, CA

Postby mlegris » Tue Feb 02, 2010 9:49 pm

@MichaelEGR,

thanks but as mentioned, I already knew that. I want to understand OpenGL fundamentals so I want to know why my code fails. I actually managed to get the SpriteText demo running, I was missing this code in my view class:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. setGLWrapper(new GLSurfaceView.GLWrapper() {
  3.  
  4.             public GL wrap(GL gl) {
  5.  
  6.                 return new MatrixTrackingGL(gl);
  7.  
  8.             }});  
  9.  
  10.  
Parsed in 0.035 seconds, using GeSHi 1.0.8.4


not so obvious.. but anyhow, it works now. However the LabelMaker is very limited in texture space, I have 5 strings of an average of 4 characters each and if I make a longer one it throws an out of space exception..

So I am guessing the way the Rokon platform works is best, however that one is throwing errors when I run his demos. I will investigate more.

If anyone can tell me what is wrong with my code, I'd really appreciate it. It is just initialization code for GL then a repetition of 5 instructions over and over again.. so it`s not hard to interpret I don't think. Thanks in advance!

Martin
mlegris
Freshman
Freshman
 
Posts: 2
Joined: Mon Feb 01, 2010 10:48 pm
Location: Montreal, QC

Postby MichaelEGR » Wed Feb 03, 2010 1:59 pm

"thanks but as mentioned, I already knew that."

Not to be overly glib and whatnot, but I don't believe you understood a thing I wrote previously.

In general you are not asking a question, but you are pleading for debugging help. I have an hourly rate if you want debugging and lessons. You can't expect a thoughtful reply the way you are presenting your issue. You could be doing any number of fundamental things wrong like you posted in a follow up about not even copying the demo you are modifying correctly.

I'll describe an approach I use that works for both desktop Java / OpenGL and Android again, but first off while SpriteText is a demo it's just that, a demo, and not the end all be all of text rendering nor a good solution to use in your or other applications. A reasonable place to start perhaps, but it's flawed.

What I described was an entirely separate process of creating a single square power of 2 texture that contains all of the ascii characters rendered via the Android 2D API (any font / any size; within reason / dependent on largest GL texture size support). The next step is indexing using the font metrics support of the Android 2D API rectangles with proper font spacing via triangle strips and also store texture coordinates for all ascii characters in the single texture. One can use vertex arrays or vertex buffer objects, call glDrawArrays with ascii characters represented as bytes which correspond to the indexed characters in the vertex and texture VA/VBO. You may recall the getBytes method of Java strings or you can cache and even modify a byte array directly since strings are immutable. That way you can do something like this..

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. byte fpsStringBytes[] = new String("Your FPS is:    ").getBytes();
  3.  
  4.  
Parsed in 0.035 seconds, using GeSHi 1.0.8.4


and in each frame simply replace fpsStringBytes[14/15/16] with the individual characters for the current frames FPS then send that modified byte array off to a simple loop using the byte array to draw each character as per above. This is one efficient way to do it.


Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public GL wrap(GL gl) {
  3.  
  4.    return new MatrixTrackingGL(gl);
  5.  
  6. }
  7.  
  8.  
Parsed in 0.035 seconds, using GeSHi 1.0.8.4


While you forgot to copy this from the SpriteText demo source code I'm going to take it that you don't really understand it's significance or why it is included or used at all. On the G1 with Android 1.0 when SpriteText was written (presumably before G1 release) it did not support glGetFloatv GL11 command. When calling this GL function the G1 will throw an UnsupportedOperationException (it may still on the Nexus One, dunno I don't have one) and presumably other devices though there is no full understanding of which devices support even some of the fundamental GL calls. So MatrixTrackingGL wraps a gl context, but inefficiently provides a facade and in software simulates the modelview and projection matrices that in a working implementation of GL on a device can be retrieved by glGetFloatv.

"Also I tried the sample in APIDemos called "SpriteText" and it throws runtime errors.. weird."

It's not weird. It doesn't work because the GL APIDemos are horribly out of date and only worked on initial Android OS releases and Google never updated the demos. Ooops. I believe they broke around Android 1.5, but def by 1.6/2.0.

"So I am guessing the way the Rokon platform works is best, however that one is throwing errors when I run his demos. I will investigate more."

I suggest you google search like I suggested "opengl font renderering" and read about the numerous ways to load fonts & render text in OpenGL and/or OpenGL ES. It wouldn't hurt picking up the red book and an Opengl ES book (look on Amazon). Learning OpenGL/ES from broken Android demo code is not recommended.

So... I suggest that in the future you find an actual question to ask rather than pleading in a slightly snide way for debugging services. OpenGL and definitely OpenGL ES on Android falls under TANSTAFL (well, for now at least... ;P). I'm not trying to discourage and such and maybe I misread your inflection, but almost everything you are doing is wrong and there is no way to help you easily.
Founder & Principal Architect; EGR Software LLC
http://www.typhonrt.org
http://www.egrsoftware.com
User avatar
MichaelEGR
Senior Developer
Senior Developer
 
Posts: 147
Joined: Thu Jan 21, 2010 5:30 am
Location: San Francisco, CA

Top

Return to Android 2D/3D Graphics - OpenGL Tutorials

Who is online

Users browsing this forum: No registered users and 3 guests