How can I blend between my UIView and my EAGLView? - iphone

I have an opengl scene rendering on an EAGLView layer and some other elements (circles and such) rendering on a UIView (which is a sibling of the EAGLView, positioned above it). Is it possible to blend colors between the two layers? I'd like to do some difference blending to get an inversion effect on the colors from EAGLView.
I've been playing around with CGBlendMode but it only seems to affect what I'm drawing in that current view. I think this has something to do with the CGContext but I'm a little hazy on the details, can I force the UIView and the EAGLView to have the same CGContext so that the blending works between them?
Help, corrections, clarifications are all appreciated. Thanks in advance,
-S

Short answer is you can not. Long answer follows.
By EAGLView you must mean the subclass of UIView that is included in the OpenGL ES Template in Xcode. What makes this class special is that the layerClass class method is overridden and return the CAEAGLLayer class instead of the CALayer class, as is default.
UIView and CALayer work in pairs. All UIView objects are backed by a CALayer, the CALayer is the object responsible for layout and rendering to screen. The UIView is a delegate to the CALayer, and is responsible for drawing it's graphics when needed.
CALayer will let it's delegate (the UIView) draw into a CGContextRef. It is one context per UIView, so you can not use CGBlendMode to blend several views since it will only function within one single UIView context.
Blending of CALayer should be done using the filter properties. These are defined for iPhone OS but the available filters are undefined according to the documentation. This is because Core Image is not available on iPhone OS at this time.

I don't think you'll be able to blend colours in that sense. The best you can do is have one completely obscuring the other, or have the top layer semi-transparent (in which case, you'll see the part underneath) - but you won't be able to do XOR type drawing.

Related

iPhone - Using CALayers instead of UIViews

I've always been told that if you want to display things into a view, you must add subviews into it and then draw into those subviews.
And today, I see that question (searching for something else) : IPhone SDK: Camera access?
In the accepted answer, I see that its author uses CALayers to draw 4 sub "views" into the main view, but all of this only based on CALayers...
So I wonder... Why ? Is this a correct way of doing ? What could lead me to use seblayers instead of subviews ?
I've been using both UIViews and CALayers. It really depends on what you want and need. UIView uses CALayer in the background, so you're using CALayers in either case. Note that there's a layer property in UIView of the type CALayer. However, coding directly with UIView is easier but it doesn't expose the full powers of Core Animation. Coding with CALayer does expose you to Core Animation and a dozen of other APIs.
If you're just concerned adding subviews, either approach would work. You can think UIView hides some of the CALayer implementation details.

change color and width of some painted lines in an UIImageView

I'm painting some black lines in an UIImageView (in touchesBegan and touchesMoved methods) and there is one UISlider for modifying the width of these lines and some buttons for modifying the color of them.
How can that be done using CoreGraphics?
...
UIGraphicsBeginImageContext(theImage.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, theNewWidth);
...
Thanks
First, you shouldn't be trying to draw on a UIImageView. Instead, create your own subclass of UIView and override -drawRect:. When the events for those UI controls are fired, just call -setNeedsDisplay on your view class to ask it to be redrawn. Also, set some properties on your view class (e.g., lineWidth, lineColor).
In -drawRect:, use Core Graphics to redraw your view with the new values the user specified.
You can look at the Quartz 2D Programming Guide for all the information you need about drawing with Core Graphics. Also, check out the QuartzDemo sample project from Apple. It demonstrates many, if not all, of Core Graphics's capabilities.

Caching Quartz Rendered Drawing Into CALayer

I'm in the process of trying to tweak the process of a game which uses Quartz to draw a moderate number of sprites, around 50, during each game loop (40 fps).
At the moment I have a very simple drawing mechanism where a single game view (UIView) iterates over all the active sprites and asks each one to render itself to a CGContext (that of the view). This works fine, but performance is starting to drop with more than 50 active objects and I'd quite like to tweak things.
I've decided that holding a CALayer for each sprite which its cached drawing is the way to go - then using Core Animation to render/rotate/scale the drawing.
I'm struggling to understand how I achieve this. Where exactly do I initially draw to? I don't have a CGContext when my sprite is initialised. Is the right approach to render to a CGImage as a buffer then set it as the content on the CALayer?
Just subclass CALayer and do your drawing in drawInContext:. The layer will then cache its contents automatically. If you don't want to subclass CALayer, you can also assign it a delegate (which must not be a UIView) and implement drawLayer:inContext:.

What's the difference between CALayer -drawInContext: and -renderInContext:?

What's the difference between CALayer -drawInContext: and -renderInContext: ?
When providing custom Quartz-drawn content to display within a CALayer, you can override -drawInContext: and do your custom drawing there. This is similar to -drawRect: for a UIView or NSView. Alternatively, you can set another class to be the delegate of the CALayer and implement -drawLayer:inContext: to provide custom content to a standard CALayer.
You don't override -renderInContext:, but instead you can call this on a layer to render it and all of its sublayers into a particular Core Graphics context. Note that this won't render certain types of layers (like those with OpenGL content). It also doesn't behave the way you'd expect when rendering into a PDF context, where the layers will come out as bitmapped rectangles instead of pure vector elements. To work around this, you might want to check out the Core Plot framework's CPTLayer implementation, where we bypass the normal rendering process in order to preserve the vectors in a PDF generated from our CALayer subclass.

Drawing a CGLayer outside the method drawRect: faster?

I'm not really sure, what am I asking...
...but if make layer composites in separate methods, and draw them to the view also outside of the drawRect: method... ...then could my app performance get raised?
I'm actually subclassed a puzzlePiece:UIView class, where the puzzlepiece gets rendered, but the redraw invoked now with setNeedsDisplay since the drawing implementation takes place in the drawRect: method. The app lags.
Can I improve performance if I get rid of the so called drawRect: method?
The thing wants to get implemented: http://gotoandplay.freeblog.hu/
I think what you want to do here is to have a very single, simple UIView that covers the entire play area. Then put each tile in a CALayer, and attach all the CALayers to the UIView and move them around and rotate them. Then there should not need to be a -drawRect: at all. You'll do all your drawing in your layers, and you should get the best performance that way. CALayer is similar to UIView in principle, but much lighter weight (faster and simpler). CALayer is basically a view that can only draw; it can't handle touches or events. It's parent view has to do that for it. But that let's CALayer be much faster.