-3

I wish to render vector shapes (CGPath) using Metal to an offscreen texture. However as I see, it is very difficult to draw thick lines using Metal which takes care of antialiasing and other issues. So it's going to involve lot of work to draw arbitrary CGPaths using Metal. I was thinking if one could use SpriteKit (which is based on Metal) to achieve the same thing. It is not clear how to use SKRenderer class to render arbitrary CGPath to Metal texture.

Deepak Sharma
  • 5,577
  • 7
  • 55
  • 131
  • As you mention; SpriteKit uses Metal so I don't understand why that would help. For vectors, I think you are better off tessellating the vector geometry to triangles than you would be rendering sprites/particles. As for antialiasing, you have control from no anti-aliasing to high quality anti-aliasing. – Jeshua Lacock Feb 19 '22 at 20:56
  • @JeshuaLacock it's simply not easy to render arbitrary geometry using Metal, that's the reason we have libraries such as nanoVG for rendering vector shapes (there is a Metal port for the same), but not without limitations. SpriteKit on the other hand is Apple's framework that internally uses Metal for rendering and has number of other interesting features. – Deepak Sharma Feb 19 '22 at 21:23
  • Umm, I didn't say anything about being easier and I know what SpriteKit is. Again, how does SpriteKit resolve your concern about performance? – Jeshua Lacock Feb 19 '22 at 21:52
  • 1
    yes you can do render-to-texture in spritekit. however if by "offscreen texture" you mean render to a *buffer* that a shader can use, then no i don't think that spritekit can render to a buffer in that way. (or, i should say, i use shaders within spritekit and i've never been able to figure out how to write to a shader buffer.) if you want example of render-to-texture, let me know, i can post one. – Fault Feb 23 '22 at 16:02
  • Yes I need to render to texture(MTLTexture) that shader can use. Which texture type are you referring to? – Deepak Sharma Feb 23 '22 at 16:57
  • Spritekit can render to a `SKTexture` as documented [here](https://developer.apple.com/documentation/spritekit/skview/creating_a_new_node_by_rendering_to_a_texture). sorry i'm not aware of how to get that into an MTLTexture that a shader can use, but perhaps it's possible – Fault Feb 24 '22 at 12:44
  • It's possible using `SKTexture`'s `cgImage()` function that can then be converted to a `MTLTexture`, but I am not aware of a more direct way. – Jeshua Lacock Feb 26 '22 at 03:27

1 Answers1

-2

The following code will create a MTLTexture from a CGPath using SKScene.

import SpriteKit
import MetalKit

class PathScene: SKScene {
    
    let device = MTLCreateSystemDefaultDevice()!
    
    override func didMove(to view: SKView) {
        
        //This is not needed if you supply your own CGPath
        let bezPath = UIBezierPath(ovalIn: self.frame.insetBy(dx: 50, dy: 50))
        
        let lineNode = SKShapeNode()
        lineNode.path = bezPath.cgPath //Use existing CGPath here
        lineNode.lineWidth = 8.0
        lineNode.strokeColor = UIColor.blue
        lineNode.name = "line"
        
        self.addChild(lineNode)
        
        guard let scene = self.scene else {return}
        
        if let skTexture = self.view?.texture(from: scene) {
            let cgImage = skTexture.cgImage()
            let loader = MTKTextureLoader(device: device)
            let mtlTexture = try! loader.newTexture(cgImage: cgImage, options: nil)
        }
        
    }

}
Jeshua Lacock
  • 5,730
  • 1
  • 28
  • 58
  • The problem with cgImage approach is data transfer from GPU to CPU and back again. I think one needs to find an SKRenderer based approach. – Deepak Sharma Feb 27 '22 at 06:38
  • 1
    You did not specify that it must remain on the GPU in your question so I did in-fact answer your OP. – Jeshua Lacock Feb 27 '22 at 06:48
  • One could simply use CPU to render CGPath then, what is the use of Metal based approach then? – Deepak Sharma Feb 27 '22 at 06:57
  • Because the rendering is done with SpriteKit like you wanted which is done with Metal under the hood. – Jeshua Lacock Feb 27 '22 at 06:57
  • I did downvote your question because I asked for clarification and you told me what I already knew - that SpriteKit is based on Metal. I asked specifically why you thought SpriteKit would resolve your concerns about performance and you did not answer. On the other hand, I spent time trying to help you and you repay me with a downvote, even though it does directly answer your OP. – Jeshua Lacock Feb 27 '22 at 20:14
  • @JeshuaLacock Yup, I know I can see that info for myself. But as You can see, its seems not possible when it comes to other profiles. – Whirlwind Feb 27 '22 at 23:15
  • I corrected myself. What more do you want? – Jeshua Lacock Feb 27 '22 at 23:16
  • Nothing, just made confirmation of what You said. Maybe my wording was bad, sorry. – Whirlwind Feb 27 '22 at 23:17
  • @JeshuaLacock Please edit your answer a bit so that I can undo downvote – Deepak Sharma Feb 28 '22 at 07:15