Swift: Make Translucent Overlapping Lines of the Same Color Not Change Color When Intersecting

Swift: Make translucent overlapping lines of the same color not change color when intersecting

This is a technique. It does not solve your problem, nor directly answer your question. Instead it offers a way to have the desired result, but without the flexibility and inherent nature of lines you actually want.

You can create textures from anything you draw with any number of nodes, with any number of techniques.

You do this (easiest way) by attaching all the drawing elements to a single node, within an SKView space that you have access to, and then render the "parent" node of your drawn objects to a texture.

How does this help?

I'm glad you asked:

You can draw everything at an opacity level of 100%, and render it to a texture, then take that texture of your drawings, put it where you like, and reduce its opacity to any percentage you like, and get an even result. No bright spots where things overlay each other.

Here's code that does all the above:

   var points = [CGPoint]()

points = [CGPoint(x: -100, y: 100), CGPoint(x: 100, y: -100)]
let FirstLine = SKShapeNode(points: &points, count: points.count)
FirstLine.strokeColor = UIColor.init(red: 0.25, green: 0.62, blue: 0.0, alpha: 1)
FirstLine.lineWidth = 30
// ^^ Note the FirstLine is not added to the Scene

points = [CGPoint(x: 100, y: 100), CGPoint(x: -100, y: -100)]
let SecondLine = SKShapeNode(points: &points, count: points.count)
SecondLine.strokeColor = UIColor.init(red: 0.25, green: 0.62, blue: 0.0, alpha: 1)
SecondLine.lineWidth = 30
FirstLine.addChild(SecondLine)
// ^^ Note SecondLine being added to FirstLine, and that they both have alpha of 1

// Now the magic: use the view of the SKScene to render FirstLine and its child (SecondLine)
// They are rendered into a texture, named, imaginatively, "tex"

let tex = view.texture(from: FirstLine)
let cross = SKSpriteNode(texture: tex, color: .clear, size: (tex?.size())!)
cross.alpha = 0.5

// ^^ The alpha of the above sprite is set to your original desire of 0.5
// And then added to the scene, with the desired result.
addChild(cross)

and here's the result:

Sample Image

Overlapping UIViews of Differing Color and Alpha

On iOS the only blending mode for views if the so-called "source over" mode.

Basically RGB_result = RGB_back * (1 - Alpha_front) + RGB_front * Alpha_front

Thus a red (1, 0, 0) view with 0.5 alpha on top of a blue (0, 0, 1) view will result in dark magenta (0.5, 0, 0.5)

If you need some other blending mode, consider drawing with CoreGraphics (e.g. CGContextSetBlendMode)

Color a sprite a different color from its texture

You can always add an overlay using an SKCropNode and a white sprite node if you need it to go white.

Basically:

    let croppedNode = SKCropNode()
croppedNode.maskNode = sprite.copy() as? SKNode
sprite.addChild(croppedNode)
let whiteNode = SKSpriteNode(color:.white,size:sprite.size)
croppedNode.addChild(whiteNode)
croppedNode.zPosition = 1

SKShapeNode .strokeColor to look same as .fillColor when change node.alpha

Though it is possible to set alpha of node's stroke directly by getting its' colors' HSBA and reassigning a new color with different alpha to the stroke (for more info look this answer), as the node's fill covers node's stroke, stroke's alpha must be set to 0 so that it actually wouldn't be seen. But this canceles antialiasing.

So it appears, that the only way to achieve smooth node's edges with no stroke be seen, is to convert SKShapeNode to SKSpriteNode and reset sprite.alpha to desired.

smooth

Here is a code snippet in Swift

let sprite = SKSpriteNode(texture: self.view!.textureFromNode(shapeNode))

Its' not that bad, because, according to Apple's docs

The node being rendered does not need to appear in the view’s
presented scene.

However, you still have to have access to the view from where the conversion takes place.



Related Topics



Leave a reply



Submit