I am writing my own 2D game for android. So far I've been using some home brew graphics - drawing frame-by-frame on a canvas with a surfaceview. I've been able to draw a variety of lines, shapes and bitmaps with solid performance.
I am wondering if it is possible (or if anyone has clever ideas) to apply certain effects to an entire canvas. For instance, it would be cool if I could add some changing gaussian blur effect to simulate movement. I have found tutorials on how to apply a gaussian blur to a bitmap, but I need to apply it to my entire canvas (which is made up of a bitmap with shapes drawn in front of it).
Any suggestions?
Once something is renderer in the hardware backbuffer, it's very hard to get access to it, it's slow, if not entirely impossible.
The standard way to make a performant post process effect is to render everything in an image or texture you created yourself. You then apply whatever effect you want to that texture, or use that texture to render in the back buffer using your effect.
Related
I've got a an OpenGL scene rendered with a bunch of sprites, and I'd like to automagically add drop shadows to all of them. Here's a picture showing what I mean:
The scene uses orthographic projection, the sprites are textured quads, and I'm using the depth buffer to draw them front to back. I'm working with OpenGL ES 2.0, but thoughts from the iOS or non-ES worlds would be appreciated as well. I've tossed a few ideas around in my head of how I can go about this, and I'd like to find out which has the most promise.
Draw each sprite twice, the first normally, the second with some kind of drop shadow shader a bit deeper in the scene. Not sure if this is possible?
Draw a sprite, then draw it again, darkened and with some alpha, several times with some random jitter applied to the verticies. This may look silly and not at all like a shadow.
Draw the base scene without background to a texture, then blur and darken it to create one large drop shadow. Then draw the base scene over the drop shadow texture, then finally over the background. This would lose the shadows between sprites, though.
SSAO in a post-processing pass. Might be the most dynamic and automatic, but could look fuzzy/grainy and really slow things down.
At creation time, generate a shadow texture for each sprite. For rendering, draw a sprite and then its shadow texuture a bit deeper in the scene. I think I'd like to avoid this due to the loading time and extra memory requirements, but this may be the fastest and best looking?
I don't want to do any shadow work with external textures, since I use the same sprite textures at varying scales, and pre-baked shadows would scale unnaturally.
So are any of these better than the others? Are there other options I'm not thinking of? Thanks!
Those are all some well thought out options, here are my thoughts on each
It is definitely possible to use a shader but it might not be the most performant option, since the blurring will have to be done inside the shader and might involve multiple texture lookups.
Drawing the texture multiple times would work and would look like a shadow, because each "jittered" image would have slightly modified alpha values. But again, blending and multiple renders of each sprite would add up and might affect performance.
I like and recommend this option, because you can set a shader that puts black pixels instead of colored pixels (considering alpha) into a render target smaller than the screen (1/4th?) and then use this as the shadow texture. Since the texture is now being stretched, you'd get the "blurring" for free, too. The pixel shader that does the "blackening" would be very simple and not affect performance too much.
Unless you really need high-quality shadows (and the previous method doesn't suffice) I wouldn't recommend this.
This is of course the most flexible option and has an x2 rendering complexity. Unfortunately, it will consume more memory than all the other options above.
Hope this helps!
I want to make brushes displayed in below image for drawing application. Which is a suitable method - Open GL or Canvas & How can we implement it?
I'd say Canvas, as you'll want to modify an image. OpenGLES is good for displaying images, but does not (as far as I know) have methods for modifying its textures (unless you render to a texture that then render to screen with some modifications, which is not always so effective).
Using the Canvas you will have the methods for drawing your brush-strokes onto the Bitmap you're painting on, in GLES you would have to modify a texture (by using a canvas) and then upload that to the GPU again, before it could be rendered, and the rendering would most likely just consist of drawing a square with your texture on it (as the fillrate for most mobile GPUs are quite bad, you don't want to draw the strokes separately).
What I'm trying to say is; The most convenient way to let the user draw on an openGLES surface would be by creating a texture by drawing on a Canvas.
But, there might still be some gain in using GL for drawing, as the Canvas-operations can be performed off-screen, and you can push this data to a gl-renderer to (possibly) speed up the on-screen drawing.
However; if you are developing for Android 3.x+ you should take a look at RenderScript, (which I personally have never had a chance to use), but seems like it would be a good solution in this case.
Your best solution is going to be using native code. That's how Sketchbook does it. You could probably figure out how by browsing through the GIMP source code http://www.gimp.org/source . Out of Canvas vs OpenGL, Canvas would be the way to go.
It depends. if you want to edit the image statically, go with canvas. But if you want after brushing the screen, to have the ability to edit, scale, rotate, it would be easier with opengl.
An example with opengl: Store the motion the user do with touchs. create a class that store a motion and have fields for size, rotation etc. to draw this class, just make a path of the brush image selected following the stored motion.
What I'm trying to do is have a background image, for sake of simplicity, lets say it's a picture of the front of a house. Then, I want to have a red ball move from window to window.
**I want to have a background picture, and a picture on top of it.
**I then want to be able to tell the top picture EXACTLY where to go.
How can I do this?
I'm just beginning to learn about animations in Android, and have not yet run across any way to do this.
There are two routes to animation in android: Canvas and OpenGL ES.
I would recommend OpenGL for anything requiring smoothness and speed, like a moving ball.
You should create a view using the helper class GLSurfaceView
http://android-developers.blogspot.com/2009/04/introducing-glsurfaceview.html, and implement a Renderer.
I assume you have the images saved in your res/drawable folders, in a format like png and the ball file contains an alpha channel.
You can see many tutorials online, but basically you need to load your background image and your ball resource at onSurfaceCreated and store it in a texture using GLUtils.texImage2D.
In the onDrawFrame method, you should set up a 2D projection such as glOrtho2D, then draw the background.
Then just before you draw the ball texture, you can use the glTranslate(x,y,0) function to move the ball over the house. Use an alpha blend for the ball:
glBlendFunc(GL_SRC_ALPHA, GL_SRC_ONE_MINUS_ALPHA);
glEnable(GL_BLEND);
Unfortunately writing in OpenGL isn't as straightforward as you might hope. Everything is done with 3D coordinates, despite the fact you want only a 2D image. But hopefully this gives you enough info to google for good exmaples, which are abundant!
I have a drawing app where the user can draw lines with their finger, adjust the color, thickness, etc. As the user is drawing, I am converting the massed X/Y points from MotionEvent into SVG Paths, as well as creating Android Path's and then drawing the Android Path's to the screen via a Canvas, and committing the SVG Path's to the app's database.
I am following the model used in FingerPaint, in that the 'in progress' lines are drawn on the fly by repeated calls to invalidate() (and thus, onDraw()), and once the line is complete and a new line is started, the previous line(s) are drawn in onDraw() from the underlying Canvas Bitmap, with in progress lines again generating repeated re-draws.
This works fine in this application - until you start rotating the underlying Bitmap to compensate for device rotation, supporting the ability to 'zoom in' on the drawing surface and thus having to scale the underlying Bitmap, etc. So for example, with the device rotated and the drawing scaled in, when the user is drawing, we need to scale AND rotate our Bitmap in onDraw(), and this is absolutely crawling.
I've looked at a SurfaceView, but as this still uses the same Canvas mechanism, I'm not sure I'll see noticeable improvement... so my thoughts turn to OpenGL. I have read somewhere that OpenGL can do rotations and scaling essentially 'for free', and even seen rumors (third comment) that Canvas may be disappearing in future versions.
Essentially, I am a little stuck between the Canvas and OpenGL solutions... I have a 2D drawing app that seems to fit the Canvas model perfectly when in one state, as there are not constant re-draws going on like a game (for instance when the user is not drawing I don't need any re-drawing), but when the user IS drawing, I need the maximum performance necessary to do some increasingly complex things with the surface...
Would welcome any thoughts, pointers and suggestions.
OpenGL would be able to handle the rotations and scaling easily.
Honestly, you would probably need to learn a lot of OpenGL to do this, specifically related to the topics of:
Geometry
Lighting (or just disabling it)
Picking (selecting geometry to draw on it)
Pixel Maps
Texture Mapping
Mipmapping
Also, learning OpenGL for this might be overkill, and you would have to be pretty good at it to make it efficient.
Instead, I would recommend using the graphic components of a game library built on top of openGL, such as:
Cocos2d
libgdx
any of the engines listed here
Well, this question was asked 6 years ago. Maybe Android 4.0 has not come up?
Actually, after Android 4.0 the Canvas at android.view.View is a hardware accelerated canvas, which means it is implementd by OpenGL, so you do not need to use another way for performance.
You can see the https://github.com/ChillingVan/android-openGL-canvas/blob/master/canvasglsample/src/main/java/com/chillingvan/canvasglsample/comparePerformance/ComparePerformanceActivity.java to compare the performance of normal canvas in view with GLSurfaceView.
You are right that SurfaceView uses Canvas underneath the hood. The main difference is that SurfaceView uses another thread to do the actual drawing, which generally improves performance. It sounds like it would not help you a great deal, though.
You are correct that OpenGL can do rotations very quickly, so if you need more performance that is the way to go. You should probably use GLSurfaceView. The main drawback with using OpenGL is that it is a real pain to do text. Basically you have to (okay, don't have to, but seems to be the best option) render bitmaps of text.
I am developing a 2d sprite-based game with a bunch of animations. Developed with separate threads and in general everything is great.
I recently added a level that has a alpha PNG graphic drawn over the Canvas after the rest of the animated bitmaps have been drawn.
There is now a noticeable speed degradation on this level and it seems to sputter etc... to top it off I just added a Multiply Xfermode to the paint for the graphic and it went to a stand-still.
Is there a better way to overlay graphics in this fashion to avoid the hit in performance (I'm assuming it has to calculate the alpha channels and it apply it to the canvas bitmap)? Is there an alternative to drawing the overlay with a drawbitmap/png?
To get better performance you could put your overlay in another window, either by using WindowManager.addView or by using a PoupWindow. The composition will then be done on the GPU.