As of iOS 16, I am seeing strange behaviour in SKEffectNode where the attached shader appears to be affecting an area that is outside the accumulated frame. This happens when the frame of the effect node's subview is changed.
I've prepared the following playground example which allows for reproduction of what I believe to be a bug. It consists of an SKScene, with an SKEffectNode added to it and an SKLabel added to the effect node. The effect node has a simple SKShader attached which produces a gradient effect across the frame of the SKLabel. A tap down on the scene will iterate the text of the SKLabel though 3 strings of different lengths. The issue presents itself by the fourth tap, as the gradient will then appear outside of the SKLabel frame. The accumulated frame of the SKEffectView at this point will also not be the same area that is affected by the shader.
import PlaygroundSupport
import SpriteKit
class GameScene: SKScene {
private var i = 0
private let strings = ["Test", "Testing", "Test Test Test"]
private let effectNode = SKEffectNode()
private let label = SKLabelNode()
override func didMove(to view: SKView) {
backgroundColor = .white
anchorPoint = CGPoint(x: 0.5, y: 0.5)
addChild(effectNode)
effectNode.position = .zero
effectNode.shouldEnableEffects = true
effectNode.shader = SKShader(source: """
void main() {
vec4 texel = texture2D(u_texture, v_tex_coord);
vec4 color = vec4(1.0-v_tex_coord.x, 0.0, 0.0, 1.0);
gl_FragColor = mix(texel, color, 0.5);
}
""")
effectNode.addChild(label)
label.verticalAlignmentMode = .center
label.position = .zero
label.fontName = "Helvetica"
label.fontSize = 40
label.fontColor = .blue
label.text = strings.first
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
i += 1
if i >= strings.count {
i = 0
}
label.text = strings[i]
}
}
let sceneView = SKView(frame: CGRect(origin: .zero, size: CGSize(width: 500, height: 500)))
let scene = GameScene(size: sceneView.frame.size)
scene.scaleMode = .aspectFill
sceneView.presentScene(scene)
PlaygroundSupport.PlaygroundPage.current.liveView = sceneView
This unexpected behaviour is not present on iOS 15, but is currently occurring on iOS 16.0, 16.0.2 and 16.1 beta 3.