Group Group Group Group Group Group Group Group Group

raywenderlich.com Forums

iOS Metal Tutorial with Swift Part 5: Switching to MetalKit

Learn how to use MetalKit in this 5th part of our Metal tutorial series.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/976-ios-metal-tutorial-with-swift-part-5-switching-to-metalkit

Nice tutorial! One small note: OpenGL uses different clip-space coordinates than Metal (in GL, z goes from -1 to 1, while in Metal z goes from 0 to 1), so using GLKMatrix4MakePerspective doesn’t give you a matrix that properly transforms from eye space to clip space. Instead, it transforms half of the viewing volume behind the eye, causing sometimes-subtle clipping and culling issues. You can fix up the matrix you get back from GLK by setting the matrix elements that are relevant to depth by adding the following code to makePerspectiveViewAngle:

let zs = farZ / (nearZ - farZ)
q[2][2] = zs
q[3][2] = zs * nearZ
1 Like

Thanks for the note! Will use it in the next tutorial.

Thanks for your detailed Tutorial this far. :smiley:

I got one issue with MetalKit Texture Loading, when replacing:

let texture = MetalTexture(resourceName: "cube", ext: "png", mipmaped: true)
texture.loadTexture(device: device, commandQ: commandQ, flip: true) 

With:

let path = Bundle.main.path(forResource: “cube”, ofType: “png”)!
let data = NSData(contentsOfFile: path) as! Data
let texture = try! textureLoader.newTexture(with: data, options: [MTKTextureLoaderOptionSRGB : (false as NSNumber)])

The Images are now mirrored and only Bottom and Front are rendered…

Hmm, same issue here…

I tried adding this to the options dictionary for the texture loading: “MTKTextureLoaderOptionOrigin : MTKTextureLoaderOriginFlippedVertically as NSObject” But this option is only available in iOS10 so i couldn’t test it

It seems that there is a difference in texture loading for different iOS versions.
You should use TextureLoader option as @bajocode wrote. If it’s not available and you have this issue, then there are two options:

  1. Flip the image file.
  2. Flip image as a CGImage and use it

Flipping the image itself works indeed, thanks :wink:

Thanks for the tutorial Andriy, this does a good job at highlighting the benefits of MetalKit :slight_smile:

As a quick edit, you are instructing developers to remove this code twice:

metalLayer = CAMetalLayer()
metalLayer.device = device
metalLayer.pixelFormat = .bgra8Unorm
metalLayer.framebufferOnly = true
view.layer.addSublayer(metalLayer)

This is first removed in “Removing Redundant Code From MetalViewController.swift”, but then again in “Adding the MTKViewDelegate Protocol”.

FYI, the starter project now needs to be updated for Xcode 8 GM. This mainly involves a bunch of quick changes from “newXYZ” to “makeXYZ”.

Thanks again!

Hi! Just a question out of curiosity here. How would I go around making the final result of the tutorial work, without using a storyboard? Normally I would go and do the following in AppDelegate.swift
in application(didFinishLaunchingWithOptions)
I would make a window and add an instance of MySceneViewController to it

window = UIWindow(frame: UIScreen.main.bounds) let sceneViewController = MySceneViewController() window!.rootViewController = sceneViewController window!.makeKeyAndVisible()

But in this case I wouldn’t know what to do with the IBOutlet in MetalViewController. And the view created in MySceneViewController won’t be an MTKView but a normal UIView.

Any thoughts?

I think you need to add MTKView as a subview of your view controller. And then set it up.

Hi! Amazing tutorial :slight_smile:
But I ask me, on the last tutorial you have the updateLogic function called in the newFrame function. How can I update the logic now? Because I want to add a FPS counter, but I don’t find the right place in the code to do it :frowning:

Thank you. Sorry for delayed reply.
In the MetalViewControllerDelegate there are two methods:

func updateLogic(_ timeSinceLastUpdate:CFTimeInterval)
func renderObjects(_ drawable:CAMetalDrawable)

You can update logic in updateLogic method in MySceneViewController, after or before you animate the object.

Tell me how to create many instances of Cube.

This tutorial is more than six months old so questions are no longer supported at the moment for it. We will update it as soon as possible. Thank you! :]