Prevent `CALayer` from dropping shadow set by its parent layer - swift

Recently I've been playing around with shadows and one particular case got me really interested. Suppose I have a parent CALayer which has three oval-shaped sublayers laid in a stack. I applied shadow to the parent layer
containerLayer.shadowColor = UIColor.black.cgColor
containerLayer.shadowRadius = 10
containerLayer.shadowOpacity = 1
and this is the result I got:
But what if I didn't want the green oval to drop shadow? I continued the experiment and set fillColor of the green layer to nil to find out that this in fact does exclude it from combined shadow on the parent layer:
So I got a question: is it possible to both prevent certain layer from dropping a shadow AND preserve layer fillColor or any of that layer's sublayers?
I've tried adding a sublayer to now invisible green oval-shaped layer, but that immediately renders the shadow underneath it. Here's how it looks:
Orange square is a direct sublayer of now invisible green oval.

While this is not really what's happening, you can think of the view's layer casting the shadow.
That's why if we have two sublayers, one with a filled path and one with a stroked path, we get this:
That's also why, if the view's layer or background is not clear, we get this:
So, when we apply a shadow to the "root" layer, it and its sublayers are "flattened" and the shadow is applied to the non-clear portions.
For your example, if you want shadows on the red and blue layers, but not the green layer, you can apply the shadows to the individual sublayers:
You didn't say in your question whether or not you want the blue-layer shadow to appear overlapped on green. If not, there are a couple ways to "move it under"...
First, we can create a duplicate of the blue layer - added first - and give that layer a shadow instead of the "top" blue layer:
A little tough to tell, but we now have 4 sublayers:
Alternatively, we could set the shadow on the red layer, no shadow on green or blue, but then add a .shadowPath to the view's "root" layer:

Related

iOS Sprite Kit - SKSpriteNode - blend two sprites

Actually, I'm migrating a game from another platform, and I need to generate a sprite with two images.
The first image will be something like the form, a pattern or stamp, and the second is only a rectangle that sets color to the first. If the color was plane, it will be easy, I could use sprite.color and sprite.colorBlendFactor to play with it, but there are levels where the second image is a rectangle with two colors (red and green, for example).
Is there any way to implement these with Sprite Kit?
I mean, something like using Core image filter, and CIBlendWithAlphaMask, but only with Image and Mask image. (https://developer.apple.com/library/ios/documentation/graphicsimaging/Reference/CoreImageFilterReference/Reference/reference.html#//apple_ref/doc/uid/TP40004346) -> CIBlendWithAlphaMask.
Thanks.
Look into the SKCropNode class (documentation here) - it allows you to set a mask for an image underneath it.
In short, you would create two SKSpriteNodes - one with your stamp, the other with your coloured rectangle. Then:
SKCropNode *myCropNode = [SKCropNode node];
[myCropNode addChild:colouredRectangle]; // the colour to be rendered by the form/pattern
myCropNode.maskNode = stampNode; // the pattern sprite node
[self addChild:myCropNode];
Note that the results will probably be more similar to CIBlendWithMask rather than CIBlendWithAlphaMask, since the crop node will mask out any pixels below 5% transparency and render all pixels above this level, so the edges will be jagged rather than smoothly faded. Just don't use any semi-transparent areas in your mask and you'll be fine.

Transparent Texture With OpenGL-ES 2.0

I am trying to add a transparent texture on top a cube. Only the front face is not transparent. Other sides are transparent. What could be the problem?. Any help is appreciated.
EDIT : I found that the face which is drawn first is opaque.
3 face of the cube is drawn.
Opaque face.((This face's index is given first in GLdrawElements))
Transparent face.
You most probably ran into a sorting problem. To display transparent geometries correctly the faces of the object have to be sorted from back to front.
Unfortunately there is no built-in support for that in opengl-es (or in any gfx-library in existance). The only possibility is to sort your polygons, recreate your object each frame and draw it with correctly ordered faces.
A workaround would be using additive transparency instead of normal transparency. Additive transparency is an order independent calculation. You have to remember to turn off z-buffer writes while drawing because otherwise some geometry may be ocluded.
Additive transparency is achieved by setting both blendfunc values to GL_ONE.

Clipping in MKOverlayView:drawMapRect

I'm having an issue with drawing to areas outside of the MKMapRect passed to drawMapRect:mapRect:zoomScale:inContext in my MKOverlayView derived class. I'm trying to draw a triangle for each coordinate in a collection and the problem occurs when the coordinate is near the edge of the MKMapRect. See the below image for an example of the problem.
In the image, the light red boxes indicate the MKMapRect being rendered in each call to drawMapRect. The problem is illustrated in the red circle where, as you can see, only part of the triangle is being rendered. I'm assuming that its being clipped to the MKMapRect, though the documentation for MKOverlayView:drawMapRect makes me think this shouldn't be happening.
From the documentation:
You should also not make assumptions that the view’s frame matches the bounding rectangle of the overlay. The view’s frame is actually bigger than the bounding rectangle to allow you to draw lines for things like roads that might be located directly on the border of that rectangle.
My current solution is to draw objects more than once if they are in a maprect that is slightly larger than then maprect given to drawMapRect but this causes me to draw some things more than needed.
Does anyone know of a way to increase the size of the clipping area in drawMapRect so this isn't an issue? Any other suggestions are also welcome.
I ended up adding a buffer to the rect passed in to drawMapRect:mapRect:zoomScale:inContext and using that to determine which objects to draw. This results in more objects being drawn than needed, but not by much.

How to Darken an Irregularly Shaped Transparent CALayer on the iPhone?

I'm putting an image into a CALayer that could be irregularly transparent:
theCardLayer.front = [CALayer layer];
theCardLayer.front.contents = (id)[cardDrawing CGImage];
In other words, it might be a square filling the layer or it might be an octagon that leaves the corners see-through.
I want to sometimes darken this layer, but without darkening the see-through bits. Any suggestions for how to do so in a programmatic way?
Take a look at CGBlendMode; a multiply blend, done by creating a new CGBitmapContext, drawing the image and then a grey fill, and assigning the resulting image to your layer, should work nicely.
You can use a CGShapeLayer. Set it's path to the shape you want to draw. You can also use shape layers as masks for other layers, if that's what you want.

Is there a simple way to let a layer throw an smooth shadow?

I was drawing a path into a layer. Lets say I can't access that drawing code in any way, because it comes from a compiled lib. Now I want to let that layer throw a shadow which matches the shape of its irregular content shape.
Is there an easy way to do it? Or must I draw like 20 of those layers and scale them up on every iteration, adjusting their alpha and letting the GPU do the extraordinarily heavy compositing?
every CALayer has the following properties:
shadowOpacity
shadowRadius
shadowOffset
shadowColor
shadowPath
If you set shadowOpacity to something other than 0 (the default) you'll see a shadow.
(CALayer docs)