3D Graphics with Metal | raywenderlich.com

That’s great! I’m looking forward to reading it!!! :grin:

As long as you create a pipeline state and vertex and fragment (or kernel) functions, you can do anything

:point_up_2: I love it

Hi Caroline,

I read Chapter 13 on Instancing and Procedural Generation, I love the content and I learned a lot from it. Your tip gave me an idea on how to implement shape keys animation. I wonder how did you learn all these? What should I do to learn more about doing animations with Metal?

Before learning how to program computer graphics, I learned to animate using 3d apps. I started with Animation:Master, and then Daz Studio, and then moved on to Blender and now Houdini. I’m not very good at modelling, but I spent a lot of time studying animation.

I look at the way things are done in the 3d app and work out how I can do it in code. Also, I read a number of books, or at least part of a number of books, such as Rick Parent’s Computer Animation, and all the standard Computer Graphics books such as Pete Shirley’s Fundamentals of Computer Graphics. I’ve been doing it for over ten years too, which helps :slight_smile: .

If I don’t know how to do something in Metal, I look at the DirectX equivalent and find out how to do it there. There’s a lot more information about DirectX, OpenGL and Vulkan than there is Metal, and a lot of it is conceptual, so it applies to any graphics API.

2 Likes

Hi Caroline, thanks for sharing your experience. I will check out all the resources you mentioned. :blush:

1 Like

Hi Caroline,

I’m using a 2017 MacBook Pro running Big Sur 11.2.2 and XCode 12.4. Before starting to work through your 3D Graphics with Metal video tutorial I decided to first test out your completed MetalRenderer. It compiled OK but immediately gave an error.

The error is in the

init(view: MTKView)

function associated with the line

Renderer.library = device.makeDefaultLibrary()!

It reads

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

I think that this error is related to a path to some Metal library not being set properly. Do you have any suggestions for resolving this problem?

Thank you.

@botchedphoto - Hi, and welcome to the forums!

Good idea to check out the final project first. Software moves so fast.

Which project exactly did you try? Could you give me the link?

I tried out 42. Challenge Game Over - combined-target on both macOS and iOS (and a few others). I don’t have exactly the same hardware configuration as you, but I tried on a 2019 MacBook Pro and an M1. Neither of them failed.

The later projects don’t have Renderer.library = device.makeDefaultLibrary()! as an implicitly unwrapped optional (the ! on the end), not that that should make a difference.

I know that playground libraries have changed, but not the project based ones as far as I know.

(link to solution for playground, although that won’t help you here: Chapter 4 playgrounds not compiling Xcode 12.0.1 - #3 by caroline)

Hi Caroline,

Thank you!

I downloaded the
“3-set-up-metal-in-swift” project file, https://files.betamax.raywenderlich.com/attachments/videos/2731/6f0a7035-5c5c-488c-81b6-fd149925a7a1.zip

Below is the block of code where the error occurred. I’ve read somewhere that one might need at least one file ending in
“.metal” to force XCode to locate the MTLLibrary. I have much, much to learn about using XCode and the libraries. I have found nothing in all my years seeking programming help that compares even close to the attention to details at (http://raywenderlich.com).

Best regards, Roger

class Renderer: NSObject {
static var device: MTLDevice!
let commandQueue: MTLCommandQueue
static var library: MTLLibrary!
let pipelineState: MTLRenderPipelineState

init(view: MTKView) {
guard let device = MTLCreateSystemDefaultDevice(),
let commandQueue = device.makeCommandQueue() else {
fatalError(“Unable to connect to GPU”)
}
Renderer.device = device
self.commandQueue = commandQueue
Renderer.library = device.makeDefaultLibrary()! Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
pipelineState = Renderer.createPipelineState()
super.init()
}

static func createPipelineState() → MTLRenderPipelineState {
let pipelineStateDescriptor = MTLRenderPipelineDescriptor()

// pipeline state properties
pipelineStateDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm
let vertexFunction = Renderer.library.makeFunction(name: "vertex_main")
let fragmentFunction = Renderer.library.makeFunction(name: "fragment_main")
pipelineStateDescriptor.vertexFunction = vertexFunction
pipelineStateDescriptor.fragmentFunction = fragmentFunction

return try! Renderer.device.makeRenderPipelineState(descriptor: pipelineStateDescriptor)

}
}

It’s really unfortunate that you chose that project, because it’s meant to do that!

If you play video 3, towards the end of the video at 9.10, I say “If we build the project, we should get an error because we haven’t created the shader functions yet”.

I think (but am not 100% sure), that any of the other projects should work! The very final one does, although you might want to turn your speakers down before you run it (:hear_no_evil:)