Re: Fast way to blur the background behind a Sprite Node

Hi. For the past few days, I have been trying to create an SKShapeNode (a rectangle) that will be used as a menu screen moving down from the outside of the screen when a button is tapped. Everything behind the node should be blurred.

Hi, I don't know if this is ideal for what you want, but I was trying to do a similar thing, except the entire background would be blurred. I found the following things key to helping reduce frame rate hit...

1. I think the higher the blur inputRadius, the slower it is. 4 blurs it enough for my situation.

2. Lower resolution is quicker. My scene is only 200x200 and then scaled to fit, etc. Luckily it suits the graphics style I'm doing.

3. I rendered the entire scene to a texture (view.texture(from: myscene)) and then applied that texture to a SKSpriteNode which was a child of an SKEffectNode which has the blur filter applied.

With those things applied, I'm still seeing a frame rate of at least 60fps.

moontiger is on the right track, however, it is absolutely possible to blur only a portion of your SpriteKit scene, here is how:

1. Set up a node (contentNode) within your scene that will hold all of your scene's contents, except for the blur node.

2. Add an SKEffectNode to the root of your scene, add an SKShapeNode (blurNode) as its child. Make sure that your blurNode is in front of all of the content in your contentNode by setting its zPosition.

I am actually happy with my second code in the original post. However, as I said, it also blurs all nodes added to the scene. Is there a way to add a node without blurring it (so that only everything below this node is blurred)?

This seems like a *very* roundabout way of achieving the desired effect. There are definitely better ways which exclusively use SpriteKit (see my original post in this thread), no UIViews or UIGraphicsImageRenderers required.

What I get is a blurred blue rectangle1, whereas I need to blue the label and the red rectange. I could have added the label and the red rectangle to background. However, they have already been added to the scene and, sure enough, the application crashes when I add them again. So, I can't do that.

The only thing that bothers me is that it takes about a second or two before the blurred image appears. Does it take so long to create fillTexture from the container? Is there a way to do it more efficiently? Can it be done in the background thread?

Thanks!

EDIT 1: Seems like the delay is obvious in Simulator and not as much on an actual device...

EDIT 2: One more issue. The blurring effect does not cover the whole scene. The edges of the scene are not blurred. Any idea why? Thanks!

There appears to be currently (as of iOS 13.x) some memory leak of IOSurface stuff when using an SKEffectNode wth CIFilters. We were using that functionality initially for blurring the playing area when a game was paused. But repeated pausing and unpausing (i.e., toggling shouldEnableEffects) would gradually pump up the number of retained IOSurfaces and memory as much as desired. We switched the code from using a CIFilter to a custom shader on the effect node; that fixed it.

There's a discussion of the memory leak issue around line 500 onwards. We ultimately used a kind of pixelated filter for the game's pause effect, but did try a Gaussian blur as well, and that blur shader is still sitting in the code (starting around line 575). It's one pass and not the classic two-pass Gaussian blur since we didn't want to make an intermediate effect node, but you could do that too if you need a large blur.

The comments there also mention an alternative approach. You can render the blurred part of the scene into an SKTexture using the view's texture(from:) or texture(from:crop:) methods, then run that texture through a CGImage -> CIFilter -> CGImage -> SKTexture -> SKSpriteNode sequence to get a regular sprite node that shows the desired effect. It's a little slow in general (probably around 1/10 of a second, enough to be noticed when you pressed the pause button in our game). For the blur case, you can avoid that lag by scaling the part to be blurred down, doing the CIFiltering, and then upscaling the result. It's blurry anyway, so you won't notice the difference. We didn't go with that method because we need a different pause effect in certain circumstances where the scaling wasn't feasible.

More Like This

Retrieving data ...

This site contains user submitted content, comments and opinions and is for informational purposes only. Apple disclaims any and all liability for the acts, omissions and conduct of any third parties in connection with or related to your use of the site. All postings and use of the content on this site are subject to the Apple Developer Forums Participation Agreement.