I'm writing a simple 2D game on Android using OpenGL ES. The problem is that, instead of actual image for some textures only white bar is rendered.
There was neither error during loading textures nor during binding them. All the textures have power of 2 size.
I'm using extension glDrawTexfOES to draw textures.
I suspect that I might be running out of GPU memory, but how do I check that? Any other ideas?
You should enhance the code in two ways:
Set tex parameters
Set crop parameters
The analogous Android call is
((GL11) gl).glTexParameteriv(GL10.GL_TEXTURE_2D, GL11Ext.GL_TEXTURE_CROP_RECT_OES, new int[]{0,0,100,100},0);
Amongst loads of other answers, there is one stating to just setup everything for 2D projection and draw a quad.
Related
I have around 2 GiB of textures (all are 256x256 tiles) in uncompressed RGBA 8888 format (the RGB 565 texture format is not an option, because there are lots smooth gradients and shades of gray, which have green tint with 565 format). So I load them on demand, when they should become visible and delete the old ones. The problem is, that there is an annoying FPS drop when I upload them OpenGL. Currently using OpenGL ES 1.1.
I decode the textures in a separate thread (i.e. BitmapFactory.decodeStream(...)) and then send the Bitmap to GL thread and upload it as a texture. When this happens the GL thread is sometimes slowed-down a bit for this upload. I measured the texture upload time and mostly it varys from 1-8ms, in average it is ~2ms. But from time-to-time it is 40-70ms. What can cause this drop?
I also generate mipmaps on the GPU (disabling mipmaps does not affect this behaviour) and here are all the texture parameters:
GLES11.glTexParameterf(GLES11.GL_TEXTURE_2D, GLES11.GL_TEXTURE_MIN_FILTER, GLES11.GL_LINEAR_MIPMAP_NEAREST);
GLES11.glTexParameterf(GLES11.GL_TEXTURE_2D, GLES11.GL_TEXTURE_MAG_FILTER, GLES11.GL_LINEAR);
GLES11.glTexParameterf(GLES11.GL_TEXTURE_2D, GLES11.GL_TEXTURE_WRAP_S, GLES11.GL_CLAMP_TO_EDGE);
GLES11.glTexParameterf(GLES11.GL_TEXTURE_2D, GLES11.GL_TEXTURE_WRAP_T, GLES11.GL_CLAMP_TO_EDGE);
GLES11.glTexParameterf(GLES11.GL_TEXTURE_2D, GLES11.GL_GENERATE_MIPMAP, GLES11.GL_TRUE);
GLES11.glTexEnvx(GLES11.GL_TEXTURE_ENV, GLES11.GL_TEXTURE_ENV_MODE, GLES11.GL_MODULATE);
GLUtils.texImage2D(GLES11.GL_TEXTURE_2D, 0, GLES11.GL_RGBA, bmp, 0);
How can I do this better? E.g. how are Open GL video players done, when they need to load and display many frames per second? Or current web browser which render pages as tiles? Is EGL_image a good option worth looking at? Will be OpenGL ES 2.0 different?
EDIT:
The slow down of loading was because of GC-ing on the GL thread.
In addition to making sure the GC does not kick in, you could do all the bitmap generation and texture upload on a separate thread as described in my answer to a similar question: Threading textures load process for android opengl game
This would prevent you from small frame drops when the upload itself takes to long.
Finally I solved it, but not with native code, nor with EGL_image, but thanks to this video. Fortunatelly I had almost all textures in 256x256 and I am targeting Android 3.2 and newer, so for this scenario there is an easy solution:
BitmapOptions.inBitmap which will reuse one Bitmap for every new tile, so no more furios GC-ing. I had to enlarge the few bitmaps that where smaller than 256x256.
My Android app needs to display a full-screen bitmap as a background, then on top of that display some dynamic 3D graphics using OpenGL ES (either 1.1. or 2.0 - not decided yet). The background image is a snapshot of a WebView component in the same app, so its dimensions already fit the screen perfectly.
I'm new to OpenGL, but I know that the regular way to display a bitmap involve scaling it into a POT texture (glTexImage2D), configuring the matrices, creating some vertices for the rectangle and displaying that with glDrawArrays. Seems to be a lot of extra work (with loss of quality when down-scaling the image to POT size) when all that's needed is just to draw a bitmap to the screen, in 1:1 scale.
The "desktop" GL has glDrawPixels(), which seems to do exactly what's needed in this situation, but that's apparently missing in GLES. Is there any way to copy pixels to the screen buffer in GLES, circumventing the 3D pipeline? Or is there any way to draw OpenGL graphics on top of a "flat" background drawn by regular Android means? Or making a translucent GLView (there is RSTextureView for Renderscript-based display, but I couldn't find an equivalent for GL)?
but I know that the regular way to display a bitmap involve scaling it into a POT texture (glTexImage2D)
Then your knowledge is outdated. Modern OpenGL (version 2 and later) are fine with arbitrary image dimensions for their textures.
The "desktop" GL has glDrawPixels(), which seems to do exactly what's needed in this situation, but that's apparently missing in GLES.
Well, modern "desktop" OpenGL, namely version 3 core and later don't have glDrawPixels either.
However appealing this function is/was, it offers only poor performance and has so many caveats, that it's rarely used, whenever it's use can be avoided.
Just upload your unscaled image into a texture, disable mipmapping and draw it onto a fullscreen quad.
Has anyone had much success on Android with creating blurred textures using blending to blur a texture?
I'm thinking of the technique described here but the crux is to take a loaded texture and then apply a blur to it so that the bound texture itself is blurred.
"Inplace blurring" is something a CPU can do, but using a GPU, which generally does things in parallel, you must have another image buffer as render target.
Even with new shaders, reads and writes from/to the same buffer can lead to corruption because they can be done reordered. A similar issue is, that a gaussian blurring kernel, which can handle blurring in one pass, depends on neighbor fragments which could have been modified by the kernel applied at their fragment coordinate.
If you don't have the 'framebuffer_object' extension available for rendering into renderbuffers or even textures (additionally requires 'render_texture' extension),
you have to render into the back buffer as in the example and then do glReadPixels() to get the image back for uploading it to the source texture, or do a fast and direct glCopyTexImage2D() (OpenGL* 1.1 have this).
If the render target is too small, you can render multiple tiles.
I'm working on implementing picking for an OpenGL game I'm writing for android. It's using the "unique color" method of drawing each touchable object as a solid color that is unique to each object. The user input then reads glReadPixels() at the location of the touch. I've gotten the coloring working, and glReadPixels working, but I have been unable to separate the "color" rendering from the main actual rendering, which complicated the use of glReadPixels.
Supposedly the trick to working with this is to render the second scene (for input) into an offscreen buffer, but this seems to be a bit problematic. I've investigated using OpenGL ES1.1 FBO's to act as an offscreen buffer, but it seems my handset (Samsung Galaxy S Vibrant (2.2)) does not support FBO's. I'm at a loss for how to correctly render this scene (and run glReadPixels on it) without the user witnessing it.
Any ideas how offscreen rendering of this sort can be done?
if FBO is not supported, you can always resort to rendering to your normal back-buffer.
Typical usage would be:
Clear back-buffer
draw "color-as-id" objects
Clear back-buffer
draw normal
SwapBuffers
The second clear will make sure the picking code will not show up on the final image.
I have adapted lesson six of insantydesign's android examples (http://insanitydesign.com/wp/projects/nehe-android-ports/) to work for a 2d square and the texture is displaying fine but I also have other (non textured) shapes drawn on screen and the texture from the square "spills over" to them.
In my on surface created method I have the line
squaretexture.loadGLTexture(gl, this.context);
which I think may be the problem.
My question is where should I put this line in order to fix my problem?
You need to enable texturing when you want to draw textures primitives, and disable texturing when you want primitives without a texture. For example:
glEnable(GL_TEXTURE_2D);
drawObjectA();
glDisable(GL_TEXTURE_2D);
drawObjectB();
Object A will be textured, but object B won't.