I am working on an Android custom graph view that uses Canvas#drawLines and a paint object that has antialiasing turned on. My view has hardware acceleration turned on. Occasionally when I pinch zoom in/out, some of the lines in my graph will appear disjointed and they sort of taper off into a gradient. If I change to software layer or disable antialiasing, the issue goes away. Is this a bug with drawLines or does someone have an idea of what might be going on?
The first image exhibits the issue, the second image was moved slightly and demonstrates how the graph looks most of the time, with fully joined lines.
(image demonstrates issue)
(image showing how graph should look - still couple minor gaps)
I think this post by Romain Guy answers some of your question: http://android-developers.blogspot.com/2011/03/android-30-hardware-acceleration.html
Essentially, anti-aliasing is not supported by drawLines when hardware acceleration is turned on. Also remember that hardware acceleration won't always be 'better' for your app. If what you are drawing can be accelerated, your app will benefit from it, but for certain operations it might be worse.
I believe that explains why your lines appear disjointed when hardware accelerated. I'm not too sure it explains why it works when you turn anti-aliasing off, though. I'd imagine it would appear disjointed even with anti-aliasing off, but clearly that is not the case!
Try forcing a refresh after the resize gestures.
Have a look at my old Accelerometer Toy app. (Yeah, it REALLY need updating...) If you don't see the problem with that app then I can probably help.
Related
I have a really weird effect happening on Android using an HTML5 canvas. Here is the code in question, it is using is the quadratic curve:
ctx.beginPath();
ctx.strokeStyle = wave.stroke;
ctx.moveTo(wave.sx, wave.sy);
ctx.quadraticCurveTo(
wave.x, wave.y,
wave.ex, wave.ey
);
ctx.stroke();
And it draws upon itself multiple times:
http://codepen.io/EightArmsHQ/pen/9f899c4c64ab49113988055432b11a6b
Here it is on an iPhone:
But here it is on Android:
I'm saying Android but I've heard it's super smooth on a Galaxy S6.
Just as a side note I'm not very familiar with graphics (i.e. GPU etc) in general so a bit sure of what terms I should even be Googling – so please be gentle if you have any obvious solutions.
I believe what you're seeing are aliasing artefacts. The curve covers less than a pixel and for some reason, the rasterization might completely miss some of these. This seems to be explicitly when drawing quadratic curves while lines and even beziers seem to work fine for me, so you could approximate them with these.
Little prologue: I'm creating a some kind of drawing application for Android (API 14 and higher). Few months ago I've started working on it and decided to use SurfaceView as a canvas to draw on. I thought that this a good decision cause SurfaceView works directly with Graphics. And everything seemed to work fine until one day I've noticed that the drawing process is a little bit laggy. There're probably a lot of weird code down there.
Anyway, now I'm optimizing that code and stuff, and I thought, do I really need to use SurfaceView for such scenario? The main things I need from my "canvas" is to draw smooth and be able to save all the drawings to Bitmap->File on External storage (this works fine).
So, should I use the simple View or the SurfaceView? Also, it would be great to hear props and cons of your decision/proposition.
Thanks
If you want to use Canvas, you are increasingly better off with a custom View, rather than a SurfaceView. The simple reason is that Canvas rendering on a View can be hardware accelerated, while Canvas rendering on a SurfaceView's surface is always done in software (still true as of Android 5.0).
By drawing "smooth" I assume you want some anti-aliasing effects. Check the chart on the hardware acceleration page to confirm that the effects you want are supported for the Android releases you want to ship on.
As device display pixel counts get steadily higher, software rendering gets increasingly expensive, and on some devices the CPU or bus isn't fast enough to keep frame rates high. Fortunately on these the pixel density is so high that you don't really need anti-aliasing, so even if it's not supported you could ignore it until you generate your software-rendered bitmap.
Before you do anything, though, it would be wise to figure out what your source of sluggishness is. It's possible you're being slowed down by inefficiencies in your drawing code rather than pixel fill rate. Check it with some of the profiling tools.
(See also the graphics architecture doc.)
How can I do antialiasing on triangles on the entire render? Should I put it on the fragmentShader? Is there any other good solution to improve this sort of thing?
Here is my "view", with very crispy edges (not very nice).
After doing some Deep research, I found that It's in fact pretty simple, and the most comonly done is to render like there was a screen 4 times bigger (or even more than 4 times). After rendering to this much more bigger screen, the GPU will take the avarege of that area and set the pixel color based on that.
It's pretty easy to enable this with this library:
https://code.google.com/p/gdc2011-android-opengl/source/browse/trunk/src/com/example/gdc11/MultisampleConfigChooser.java
However,you should keep in mind, that it will spent 4 or more times time to render everything, meaning more time to process, and perhaps, less FPS...
Also, if you are emulating an android device with OpenGL, find out if your GPU supports this kind of Multisampling. Mine for example, doesen't (Tegra).
Here is the final result, with and without multisampling:
(I tried to stuff the question with keywords in case someone else has this issue - I couldn't find much help.)
I have a custom View in Android that contains an LED bargraph that displays levels received via socket communication. It's basically just a clipped image. The higher the level, the less clipped the image is.
When I update the level and then invalidate the View, some devices seem to "collect" multiple updates and render them in chunks. The screen visibly hesitates for say 1/10th of a second, then rapidly paints multiple frames, and then hesitates again. It looks like it's overwhelmed and dropping frames.
However, when changing another UI control on the screen, the LED bargraph paints much more frequently and smoothly. I'm thinking Android is trying to help me by "collecting" multiple invalidations and then doing them all at once. Perhaps by manipulating controls, I'm "increasing" my frame rate simply by giving it "more to do" so it delays less between actual paints.
Unlike animation (with smooth transitions) I want to show the absolute latest value as quickly as possible. My data samples aren't faster than 10-20fps anyway.
Is there an easy way to "force" a paint at certain points, or is this a limit of how Views work? Should I be implementing this in a SurfaceView instead? (I have not played with that yet... want advice first.) Thanks in advance for suggestions.
(Later that same day...)
Update: I found a page in the Docs that does suggest implementing my widget as a SurfaceView is the way to go:
http://developer.android.com/guide/topics/graphics/2d-graphics.html
(An hour after that...)
SurfaceView seems overkill for what I want to do. The best-practice method is to "own" the whole canvas, but I have already developed the rest of my controls and layouts and they work well. It must be possible to get some better performance with what I have, especially since interacting with the UI makes the redraw speed satisfactory.
It turns out SurfaceView was the way to go. I was benchmarking on an older phone which didn't help. (The frame rate using a standard View was fine on an ASUS eeePad). I had to throw away some code, but the end result is smoother and faster with SurfaceView. Further, I was able to re-use more code than I expected and actually dramatically simplified my multitouch handling code (since everything I want to touch is in the same SurfaceView.
FYI: I'm still only getting about 15fps on Droid X, but half of the CPU load appears to be data packet processing. The eeePad is doing almost 40fps now -- and my data rate is only 20 samples/sec.
So... a win I guess. I want the Droid X to run better, but it flies on a real tablet.
I' developing a small android maze game and I'm experiencing a strange effect which I can only describe via screenshot: http://www.virtualalbum.eu/fu/39/cepp1523110123182951.jpg
At first I thought I needed to set up antialiasing but the advices I followed to enable it changed nothing, and the effect appears to be a little too evident to be that anyway.
The labyrinth is composed with rectangular-based pieces for the walls and small square-based pillars between walls and on edges, plus a big square as the floor.
There are 4 lights, I don't know if that matters
I've been thinking about removing the small pillar faces adjacent to walls as you shouldn't see them anyway, but that would mean writing a lot of code and still wouldn't fix the zigzag with the floor.
Thanks a lot,
J
EDIT: After some more testing I'm starting to think it may be a z-fighting issue, does anyone has any idea on how to increase the depth buffer precision on android?
I managed to fix it, settinggl.glDepthFunc(GL10.GL_LEQUAL); the zigzag on the floor disappeared (as it's the first thing I draw), I was still having issues with the walls but for that I wrote some extra code (it wasn't that much after all) and I'm also saving some triangle.