I would like to achieve FSAA on my OpenGL ES app on the iPhone.
Currently I do this by rendering the scene to a texture that is twice the width and height of the screen. I then use the nice function:
void glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height);
to draw the image resized to the screen resolution.
Is there a better way to do this?
Update Bounty Added I was wondering, given that its now Jan 2010, whether there is a better way to do this on v3.1 3GS phones, etc.
For Gran Turismo on the PSP, the developers achieved an effect similar to anti-aliasing by moving the image back and forth one pixel per frame (demonstration can be found here: http://www.gtplanet.net/why-gran-turismo-psp-looks-so-good/) so if the iPhone doesn't support what you're looking for that's an option.
As of iOS 4.0, full-screen anti-aliasing is directly supported via an Apple extension to OpenGL. The basic concept is similar to what you are already doing: render the scene onto a larger framebuffer, then copy that down to a screen-sized framebuffer, then copy that buffer to the screen. The difference is, instead of creating a texture and rendering it onto a quad, the copy/sample operation is performed by a single function call (specifically, glResolveMultisampleFramebufferAPPLE()).
For details on how to set up the buffers and modify your drawing code, you can read a tutorial on the Gando Games blog which is written for OpenGL ES 1.1; there is also a note on Apple's Developer Forums explaining the same thing.
Thanks to Bersaelor for pointing this out in another SO question.
Technically iPhone's GPU (PowerVR MBX Lite) should support anti-aliasing. However, it seems that current Apple's OpenGL ES drivers (as of Jan 2009) don't expose this capability. So doing "manual AA" just like you do is pretty much the only way.
http://iphonedevelopment.blogspot.com/2009/06/opengl-es-2-shaders.html?showComment=1245770504079#c6001476340022842908
iPhone OS 3.0 + OpenGL ES 2.0. Is anyone seeing better anti-aliasing?
Sounds like you can't do it in hardware since you don't render to the framebuffer, only a texture that the iPhone composites for you.
Related
I am working on a cross-platform mobile game for Android and iOS devices. I am using Adobe Flash with AIR and AS3 to code the game. I am drawing my character, obstacles, and backgrounds in Adobe Illustrator. The canvas in Flash is set to 960x640. The character was intended to be 1/3 of the screen height so around 213 pixels high. I designed the character in Adobe Illustrator to be somewhere around 900 pixels high. When I imported the character into Flash I animated him, instantiated him using var player:Player = new Player(), and scaled him down to size using the scaleX and scaleY properties. I tested it out on the desktop and Android phone and it looked wonderful. However, when I tested it out on an iPhone, the player was unacceptably pixelated around the edges. I figured the fact that I drew the animation much larger than the intended height must be the problem, so I redrew the player to exactly 213 pixels high and retested on the iPhone without any improvement in the quality of the animation. I also tried converting the MovieClip to a Bitmap vector explained here but that also had no effect on the quality of the animation.
At this point, I am at a loss. Does anyone have any suggestions on how to avoid this pixelation issue that I am experiencing when going from Adobe Illustrator to Flash to the iPhone?
For a more optimised iPhone route you might want to consider creating your animation as a set of bitmap graphics, i.e. create them as png files using PhotoShop at the size you want them to be displayed at.
By doing this you'll save CPU activity in having Flash create smoothed bitmaps
Try to set smoothing to true for your bitmap.
yourbitmap.smoothing = true;
I have some solutions for your problems.
Character should not have dark outlines. Use gradients for better effects.
Color combination should understand for your character. which background you use and other things.
I need in antialiasing in iPhone 3G (OpenGL ES1.1), NOT iPhone 3Gs with OpenGL ES.2.0.
I've draw 3d model and have next: pixels on the edges of the model look like teeth.
I've try set any filters for texture, but this filters making ONLY texture INSIDE look better.
How can i make good antialising ?
May be i should use any smooth for drawing triangles ? If yes, then how it possible in OpenGL ES1.1 ?
thanks.
As of iOS 4.0, full-screen anti-aliasing is directly supported via an Apple extension to OpenGL. The basic concept is similar to epatel's suggestion: render the scene onto a larger framebuffer, then copy that down to a screen-sized framebuffer, then copy that buffer to the screen. The difference is, instead of creating a texture and rendering it onto a quad, the copy/sample operation is performed by a single function call (specifically, glResolveMultisampleFramebufferAPPLE()).
For details on how to set up the buffers and modify your drawing code, you can read a tutorial on the Gando Games blog which is written for OpenGL ES 1.1; there is also a note on Apple's Developer Forums explaining the same thing.
Thanks to Bersaelor for pointing this out in another SO question.
You can render into a larger FBO and then use that as a texture on a square.
Have a look at this article for an explanation.
Check out the EGL_SAMPLE_BUFFERS and EGL_SAMPLES parameters to eglChooseConfig(), as well as glEnable(GL_MULTISAMPLE).
EDIT: Hrm, apparently you're out of luck, at least as far as standardized approaches go. As mentioned in that thread you can render to a large off-screen texture and scale to a smaller on-screen quad or jitter the view matrix several times.
We found another way to achieve this. If you edit your textures and add for example a 2 pixel frame of transparent pixels, the colored pixels in the texture are blended with the transparent pixels when necessary giving a basic anti-aliasing effect. You can read the full article here in our blog.
The advantage of this approach is that you are not rendering a bigger image, or copying a buffer, or even worse, making a texture from a buffer, so there is no impact in performance.
Does anyone know how can i render a string on the iphone? Its for displaying my frame per second with =p
There's no built-in way of rendering text in OpenGL but two more or less common techniques: Rendering the glyphs using geometry (less common) or using texture mapping (far more common). For your case texture mapping would be very easy: Set up a CGBitmapContext and render the text using Quartz. Then upload the image in the previously generated texture using glTexSubImage2D.
On the iPhone you could also just put a UILabel on top of you OpenGL view and let UIKit do the rendering. In my application this did not hit performance at all (even though Apple claims it does).
You can use a Texture2D and the initWithString method to draw text in OpenGL. See the crash landing example that is included in the iphone sdk.
You could also use a UILabel and have it on top of the opengl layer.
As said before, Texture2D is a good idea, but Crash Landing was removed from a lot of places in Apple, what you could do , is download the Cocos2d , and then extract the Texture2D class provided there ( it's the same class provided by Apple, but with a couple of more things )
Cocos 2D for iPhone
I'm considering re-writing the menu system of my iPhone app to use Open GL just to improve the smoothness of scrolling a big image (480x1900px) across the screen.
I'm looking at doing this as a way to improve on using the method/solution as described here (Smoother UIView). This solution was a big improvement over the previous implementation but it's still not perfect and as this is the first thing the user will see I'd like it to be as flawless as possible.
Will switching to OpenGL give me the sort of smooth scrolling I'm looking for? I've stayed clear of OpenGL until now as this is my first app and core animation has handled everything else I've thrown at it well enough, would be good to know if this alternative implementation is likely to work! thanks
You should be using CATiledLayer for images that big. From the UIView docs:
Regardless of which version of iPhone
OS is running, you should consider
using a CATiledLayer object if you
need to create views larger than 1024
x 1024 in size.
Bill Dudney posted the CATiledLayer example from his Core Animation book on his blog. Unless you're building a graphics intensive game, you shouldn't need to drop down into OpenGL. Core Animation should give you all of the performance you need.
I'm developing a 2D game for the iPhone using OpenGL ES and I'd like to use a 320x480 bitmapped image as a persistent background.
My first thought was to create a 320x480 quad and then map a texture onto it that represents the background. So... I created a 512x512 texture with a 320x480 image on it. Then I mapped that to the 320x480 quad.
I draw this background every frame and then draw animated sprites on top of it. This works fine except that the drawing of all of these objects (background + sprites) is too slow.
I did some testing and discovered that my slowdown is in the pixel pipeline. Not surprisingly, the large background image is the main culprit. To prove this, I removed the background draw and everything else rendered very fast.
I am looking for advice on how to keep my background and also improve performance.
Here's some more info:
1) I am currently testing on the Simulator (still waiting on Apple for the license)
2) The background is a PVR texture squeezed down to 128k
3) I had hoped that there might be a way to cache this background into a color buffer but haven't had any luck with that. that may be due to my inexperience with OpenGL ES or it just might be a stupid idea that won't work :)
4) I realize that the entire background does not always have to refresh, just the parts that have been drawn over by the moving sprites. I started to look into techniques for refreshing (as necessary) parts of the the background either as separate textures or with a scissor box, however this seems less than elegant.
Any tips/advice would be greatly appreciated...
Thank you.
Do not do performance testing on the simulator. Ever!
The differences to the real hardware are huge. In both directions.
If you draw the background every frame:
Do not clear the framebuffer. The background will overdraw the whole thing anyway.
Do you really need a background texture ?
What about using a color gradient via vertex colors ?
Try using the 2bit mode for the texture.
Turn of all render steps that you do not need for the background.
E.g.: Lighting, Blending, Depth-Test, ...
If you could post some of your drawing code it would be a lot easier to help you.
If you're making a 2D game, is there any reason you aren't using an existing library? Specifically, the cocos2d for iPhone may be worth your time. I can't answer your question about how to fix the issue doing it all yourself, but I can say that I've done exactly what you're talking about (having one full screen background with sprites on top) with cocos2d and it works great. (Assuming 60 fps is fast enough for you.) You may have your reasons for doing it yourself, but if you can, I would highly suggest at least doing a quick prototype with cocos2d and seeing if that doesn't help you along. (Details and source for the iPhone version are here: http://code.google.com/p/cocos2d-iphone/)
Thanks to everyone who provided info on this. All of the advice helped out in one way or another.
However, I wanted to make it clear that the main issue here turned out to be the behavior of simulator itself (as implied by Andreas in his response). Once I was able to get the application on the device, it performed much, much better. I mention this because, prior to developing my game, I had seen a lot of posts that indicated that the device was much slower than the simulator. This might be true in some instances (e.g. general application logic) but in my experience, animation (particularly 3d transformations) are much faster on the device.
I dont have much experience with OpenGL ES, but this problem occurs generally.
Your idea about the 'color buffer' is good intuition, essentially you want to be storing your background as a frame buffer and loading it directly onto your rendering buffer before drawing the foreground.
In OpenGL this is fairly straight forward with Frame Buffer Objects (FBO's). Unfortunatly I dont think OpenGL ES supports them, but it might give you somewhere to start looking.
you may want to try using VBOs (Vertex Buffer Objects) and see if that speeds up things. Tutorial is here
In addition, I just saw, that since OpenGL ES v1.1, there is a function called glDrawTex (Draw Texture) that is designed for
fast rendering of background paintings, bitmapped font glyphs, and 2D framing elements in games
You could use frame buffer objects similar to the GLPaint example from Apple.
Use a texture atlas to minimize the number of draw calls you make. You can use glTexCoordPointer for setting your texture coordinates that maps each image to its correct position. Remember to set your vertex buffer too. Ideally one draw call will render your entire 2D scene.
Avoid enabling/disabling states where possible.