Metal Tutorial 0 β Preparation
Tutorial 0 β Preparation
Before writing any Metal code, this page walks you through cloning the project, understanding its structure, and the key concepts behind Metal rendering.
Prerequisites
Before diving into Metal, itβs helpful to have a solid foundation in key concepts.
Swift
- Why: Swift is the language used for iOS development, including Metal.
- Resources: Swift Programming Language Book
Graphics Fundamentals
- Why: Understanding how graphics work under the hood helps you optimize performance and troubleshoot issues.
- Resources:
- Learn OpenGL β Great for understanding the basics of rendering pipelines.
- Scratchapixel β In-depth tutorials on graphics algorithms.
Metal API
- Why: Metal is Appleβs low-level graphics framework, optimized for performance on Apple Silicon and GPUs. It abstracts hardware details while giving you fine-grained control over rendering pipelines.
- Resources:
- Metal Programming Guide β Official guide to Metal concepts and APIs.
Useful references to keep open while working through the tutorials:
Setting up the project
Clone the repository
git clone https://github.com/Fe0437/MetalTutorials.git
Launch Xcode and open the MetalTutorials.xcodeproj file to begin exploring the project structure and tutorials.
Switching between tutorials
To switch between tutorials, open MTMetalTutorialsApp.swift and modify the content view by changing the function call in the WindowGroup:
@main
struct MetalTutorialsApp: App {
var body: some Scene {
WindowGroup {
// substitute here to choose the tutorial
MT1ContentView() // β change to MT2ContentView(), MT3ContentView(), β¦
}
}
}
Each MTxContentView wires up the corresponding MTKView and renderer for that tutorial.
Files
MetalTutorials/
βββ Shared/
βββ MTMetalTutorialsApp.swift β entry point, switch tutorials here
βββ Tutorial 1 - Hello/
β βββ MT1ContentView.swift
β βββ MT1Simple2DTriangleMetalView.swift
β βββ MT1HelloShaders.metal
β βββ MT1Vertex.h
βββ Tutorial 2 - Sample Object/
β βββ MT2ContentView.swift
β βββ MT2SampleObjectMetalView.swift
β βββ MT2ObjRenderer.swift
β βββ MT2SampleObjectShaders.metal
β βββ MT2Uniforms.h
βββ Tutorial 3 - Deferred Rendering Object/
β βββ MT3ContentView.swift
β βββ MT3DeferredMetalView.swift
β βββ MT3DeferredRenderer.swift
β βββ MT3DeferredRendering.metal
β βββ MT3GBuffer.h
β βββ MT3Uniforms.h
βββ Tutorial 4 - Shadows/
β βββ MT4ContentView.swift
β βββ β¦
βββ Tutorial 5 - Tiled Rendering/
β βββ MT5ContentView.swift
β βββ β¦
βββ Tutorial 6 - GPU Rendering/
β βββ MT6ContentView.swift
β βββ β¦
βββ Resources/
βββ Obj/bunny.obj β Stanford bunny used in tutorials 2+
Each tutorial folder is self-contained and builds on the previous one. The Metal shader namespaces (MT1::, MT2::, MT3::) keep everything clearly separated.
How Metal works
GPU Render Pipeline
flowchart TD
A["Vertex Shader"] --> B["Rasterization"]
B --> C["Fragment Shader"]
C --> D["Blending"]
D --> E["Framebuffer"]
The Metal rendering loop
To understand each tutorial, follow this basic Metal rendering loop pattern:
flowchart TD
A["App launch"] --> B["MTKView created with MTLDevice"]
B --> C["MTKViewDelegate set"]
C --> D["mtkView drawableSizeWillChange"]
C --> E["draw in view called each frame"]
E --> F["MTLCommandBuffer"]
F --> G["MTLRenderCommandEncoder"]
G --> H["Draw calls"]
H --> I["present and commit"]
Understanding this loop before diving into the tutorials will make the code much easier to follow.
UIViewRepresentable pattern
flowchart TD
A["struct MyMetalView: UIViewRepresentable"] --> B["makeUIView returns MTKView"]
B --> C["makeCoordinator returns MTRenderer"]
C --> D["MTRenderer is the MTKViewDelegate"]
The tutorials target iOS and use UIViewRepresentable to embed the MTKView (a UIKit class) into SwiftUI:
struct MyMetalView: UIViewRepresentable {
typealias UIViewType = MTKView
func makeUIView(context: Context) -> MTKView { β¦ }
func updateUIView(_ uiView: MTKView, context: Context) { }
// the coordinator IS the renderer / MTKViewDelegate
func makeCoordinator() -> MyRenderer { β¦ }
}
The Coordinator pattern lets the renderer own the MTKView delegate without the view being recreated on every SwiftUI update.
Code
Tutorial 0 is a preparation guide β no code to write yet! Head to Tutorial 1 for your first Metal project.
Key concepts recap
- GPU render pipeline β Vertices are transformed by the vertex shader, rasterized into fragments, colored by the fragment shader, blended, and written to the framebuffer.
- CPU β GPU data flow β The CPU prepares vertex buffers, index buffers, and uniform buffers, then hands them to the GPU via Metal command encoders.
- Metal rendering loop β Each frame, the app creates a command buffer, encodes draw calls with a render command encoder, presents the drawable, and commits the buffer.
- UIViewRepresentable pattern β SwiftUI wraps the UIKit-based
MTKViewusingUIViewRepresentable, with aCoordinatorthat acts as theMTKViewDelegateand renderer.