Swift: make translucent overlapping lines of the same color without changing color when crossing

Currently, I have drawn two lines on the screen that have the same color but both have an alpha value less than 1. When these lines intersect, the intersection is different from the rest of the lines. There was a previous post devoted to the same problem: quick drawing of translucent lines, how to make overlapping parts not dark? However, there are not enough replies to this post. I am drawing lines currently as follows:

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: 0.5) FirstLine.lineWidth = 30 addChild(FirstLine) 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: 0.5) SecondLine.lineWidth = 30 addChild(SecondLine) 

Here's what it looks like:

I understand why this happens, but is there a way to make the intersection the same so that it looks much better?

Edit: I decided to implement @Confused answer. However, the problem now is that the texture is always centered to the middle of the screen. This is an example:

The red cross is in the correct position, since it connects the indicated points together. However, as soon as I make a red cross texture, it is always centered towards the middle of the screen (green cross - red cross as a texture). Can I use any code that could move the texture to the correct position. Note: this code cannot work only in this example, I need one that works all the time regardless of the position of the red cross.


FINAL EDIT FOR PEOPLE WITH THE SAME PROBLEM

First set it up like this:

 var points = [CGPoint]() let crossParent = SKNode() addChild(crossParent) 

Pay attention to THAT YOU SHOULD create a parent SKNode for the texture, otherwise everything on the screen will become the texture, not just the node you want. Then add the parent node element to the scene.

Then create the necessary lines (in this case, the green cross):

 //The first line of the green cross points = [CGPoint(x: -300, y: 300), 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.0) FirstLine.lineWidth = 30 crossParent.addChild(FirstLine) 

Remember to NOT add the first line created in the scene, but rather to the original SKNode that you created at the beginning. Also set the alpha value to 1.0 for each line you draw. Then add the other lines:

 //The second line of the green cross points = [CGPoint(x: -100, y: 300), CGPoint(x: -300, 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.0) SecondLine.lineWidth = 30 FirstLine.addChild(SecondLine) 

Note that you MUST add this line to the first line like this, and not to the scene. If you add more than one line after adding the first line, add it to the first line, as I did here for every sequence that you add.

Now create the texture as follows:

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

After that, everything that you call a cross will be your texture, and you can change the alpha value, as I did here, to whatever you like, and the image will not have different colors. Remember to add texture to the scene.

Finally, you may notice that the texture is not in the place where you originally set the dots. You can return it to the same position as this:

 cross.position = CGPoint(x: (FirstLine.frame.midX), y: (FirstLine.frame.midY)) 

Hope this helps :) Thanks @Confused for the texture part of the program: D


+4
source share
4 answers

This is the method. It does not solve your problem and does not answer your question. Instead, he offers a way to get the desired result, but without the flexibility and inherent nature of the lines you really want.

You can create textures from everything that you draw with any number of nodes, with any number of methods.

You will do this (the easiest way) by attaching all the drawing elements to one node, within the SKView space that you have access to, and then render the β€œparent” node of your drawn objects onto the texture.

How does this help?

I'm glad you asked:

You can draw everything at an opacity level of 100% and display it on the texture, then take the texture of your drawings, put it where you want, and reduce its opacity to any percentage that you like and get an even result. There are no bright spots where things overlap.

Here is the code that does all of 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 is the result:

enter image description here

+2
source

NO! I think that, unfortunately, is the answer.

The following blending modes exist, none of which provide the result you are looking for:

 case alpha // Blends the source and destination colors by multiplying the source alpha value. case add // Blends the source and destination colors by adding them up. case subtract // Blends the source and destination colors by subtracting the source from the destination. case multiply // Blends the source and destination colors by multiplying them. case multiplyX2 // Blends the source and destination colors by multiplying them and doubling the result. case screen // Blends the source and destination colors by multiplying one minus the source with the destination and adding the source. case replace // Replaces the destination with the source (ignores alpha). 

The only option that can work is a custom shader that calculates if it somehow overlaps itself. But I don’t have CLIEN, where you can even start doing something like that, or if it's possible.

+1
source
  • Make the color of the stroke completely opaque.
  • Add path nodes to SKEffectNode .
  • Set the alpha effect of the node to the desired value.
  • Place the node effect in the main scene.

With this, you can also put all the lines in one node form:

 let path = CGMutablePath() path.move( to: CGPoint(x: -100, y: 100)) path.addLine(to: CGPoint(x: 100, y: -100)) path.move( to: CGPoint(x: 100, y: 100)) path.addLine(to: CGPoint(x: -100, y: -100)) let shape = SKShapeNode(path: path) shape.strokeColor = UIColor(red: 0.25, green: 0.62, blue: 0.0, alpha: 1) shape.lineWidth = 30 let effect = SKEffectNode() effect.addChild(shape) effect.alpha = 0.5 addChild(effect) 
+1
source

The problem is that you are doing alpha blending at the color level, doing alpha blending at the node level

 var points = [CGPoint]() var cross = SKEffectNode() 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 cross.addChild(FirstLine) 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 cross.addChild(SecondLine) cross.alpha = 0.5 addChild(cross) 
+1
source

Source: https://habr.com/ru/post/1261688/


All Articles