Extract Terrain into its own class
This commit is contained in:
parent
ee2431d9c4
commit
5fa89d1e47
3 changed files with 89 additions and 62 deletions
|
@ -23,6 +23,7 @@
|
|||
C0C15AB9218E2A90007494E2 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = C0C15AB8218E2A90007494E2 /* Shaders.metal */; };
|
||||
C0C15ABC218E2A90007494E2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C0C15ABB218E2A90007494E2 /* Assets.xcassets */; };
|
||||
C0C15ABF218E2A90007494E2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C0C15ABD218E2A90007494E2 /* Main.storyboard */; };
|
||||
C0C15AC6218E32B3007494E2 /* Terrain.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0C15AC5218E32B2007494E2 /* Terrain.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
|
@ -49,6 +50,7 @@
|
|||
C0C15ABE218E2A90007494E2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
C0C15AC0218E2A90007494E2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
C0C15AC1218E2A90007494E2 /* Terrain2.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Terrain2.entitlements; sourceTree = "<group>"; };
|
||||
C0C15AC5218E32B2007494E2 /* Terrain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Terrain.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -122,6 +124,7 @@
|
|||
C0C15AB2218E2A90007494E2 /* AppDelegate.swift */,
|
||||
C0C15AB4218E2A90007494E2 /* GameViewController.swift */,
|
||||
C0C15AB6218E2A90007494E2 /* Renderer.swift */,
|
||||
C0C15AC5218E32B2007494E2 /* Terrain.swift */,
|
||||
C0C15AB8218E2A90007494E2 /* Shaders.metal */,
|
||||
C0C15ABA218E2A90007494E2 /* ShaderTypes.h */,
|
||||
C0C15ABB218E2A90007494E2 /* Assets.xcassets */,
|
||||
|
@ -247,6 +250,7 @@
|
|||
files = (
|
||||
C0C15AB9218E2A90007494E2 /* Shaders.metal in Sources */,
|
||||
C0C15AB5218E2A90007494E2 /* GameViewController.swift in Sources */,
|
||||
C0C15AC6218E32B3007494E2 /* Terrain.swift in Sources */,
|
||||
C0C15AB7218E2A90007494E2 /* Renderer.swift in Sources */,
|
||||
C0C15AB3218E2A90007494E2 /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
|
|
|
@ -42,7 +42,7 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
|
||||
var rotation: Float = 0
|
||||
|
||||
var mesh: MTKMesh
|
||||
var terrain: Terrain
|
||||
|
||||
init?(metalKitView: MTKView) {
|
||||
self.device = metalKitView.device!
|
||||
|
@ -61,12 +61,12 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
metalKitView.colorPixelFormat = MTLPixelFormat.bgra8Unorm_srgb
|
||||
metalKitView.sampleCount = 1
|
||||
|
||||
let mtlVertexDescriptor = Renderer.buildMetalVertexDescriptor()
|
||||
terrain = Terrain(dimensions: float2(8, 8), segments: uint2(20, 20), device: device)!
|
||||
|
||||
do {
|
||||
pipelineState = try Renderer.buildRenderPipelineWithDevice(device: device,
|
||||
metalKitView: metalKitView,
|
||||
mtlVertexDescriptor: mtlVertexDescriptor)
|
||||
mtlVertexDescriptor: terrain.vertexDescriptor)
|
||||
} catch {
|
||||
print("Unable to compile render pipeline state. Error info: \(error)")
|
||||
return nil
|
||||
|
@ -77,13 +77,6 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
depthStateDesciptor.isDepthWriteEnabled = true
|
||||
self.depthState = device.makeDepthStencilState(descriptor:depthStateDesciptor)!
|
||||
|
||||
do {
|
||||
mesh = try Renderer.buildMesh(device: device, mtlVertexDescriptor: mtlVertexDescriptor)
|
||||
} catch {
|
||||
print("Unable to build MetalKit Mesh. Error info: \(error)")
|
||||
return nil
|
||||
}
|
||||
|
||||
do {
|
||||
colorMap = try Renderer.loadTexture(device: device, textureName: "ColorMap")
|
||||
} catch {
|
||||
|
@ -95,31 +88,6 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
|
||||
}
|
||||
|
||||
class func buildMetalVertexDescriptor() -> MTLVertexDescriptor {
|
||||
// Creete a Metal vertex descriptor specifying how vertices will by laid out for input into our render
|
||||
// pipeline and how we'll layout our Model IO vertices
|
||||
|
||||
let mtlVertexDescriptor = MTLVertexDescriptor()
|
||||
|
||||
mtlVertexDescriptor.attributes[VertexAttribute.position.rawValue].format = MTLVertexFormat.float3
|
||||
mtlVertexDescriptor.attributes[VertexAttribute.position.rawValue].offset = 0
|
||||
mtlVertexDescriptor.attributes[VertexAttribute.position.rawValue].bufferIndex = BufferIndex.meshPositions.rawValue
|
||||
|
||||
mtlVertexDescriptor.attributes[VertexAttribute.texcoord.rawValue].format = MTLVertexFormat.float2
|
||||
mtlVertexDescriptor.attributes[VertexAttribute.texcoord.rawValue].offset = 0
|
||||
mtlVertexDescriptor.attributes[VertexAttribute.texcoord.rawValue].bufferIndex = BufferIndex.meshGenerics.rawValue
|
||||
|
||||
mtlVertexDescriptor.layouts[BufferIndex.meshPositions.rawValue].stride = 12
|
||||
mtlVertexDescriptor.layouts[BufferIndex.meshPositions.rawValue].stepRate = 1
|
||||
mtlVertexDescriptor.layouts[BufferIndex.meshPositions.rawValue].stepFunction = MTLVertexStepFunction.perVertex
|
||||
|
||||
mtlVertexDescriptor.layouts[BufferIndex.meshGenerics.rawValue].stride = 8
|
||||
mtlVertexDescriptor.layouts[BufferIndex.meshGenerics.rawValue].stepRate = 1
|
||||
mtlVertexDescriptor.layouts[BufferIndex.meshGenerics.rawValue].stepFunction = MTLVertexStepFunction.perVertex
|
||||
|
||||
return mtlVertexDescriptor
|
||||
}
|
||||
|
||||
class func buildRenderPipelineWithDevice(device: MTLDevice,
|
||||
metalKitView: MTKView,
|
||||
mtlVertexDescriptor: MTLVertexDescriptor) throws -> MTLRenderPipelineState {
|
||||
|
@ -144,30 +112,6 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
return try device.makeRenderPipelineState(descriptor: pipelineDescriptor)
|
||||
}
|
||||
|
||||
class func buildMesh(device: MTLDevice,
|
||||
mtlVertexDescriptor: MTLVertexDescriptor) throws -> MTKMesh {
|
||||
/// Create and condition mesh data to feed into a pipeline using the given vertex descriptor
|
||||
|
||||
let metalAllocator = MTKMeshBufferAllocator(device: device)
|
||||
|
||||
let plane = MDLMesh.newPlane(withDimensions: float2(6, 6),
|
||||
segments: uint2(20, 20),
|
||||
geometryType: .triangles,
|
||||
allocator: metalAllocator)
|
||||
|
||||
let mdlVertexDescriptor = MTKModelIOVertexDescriptorFromMetal(mtlVertexDescriptor)
|
||||
|
||||
guard let attributes = mdlVertexDescriptor.attributes as? [MDLVertexAttribute] else {
|
||||
throw RendererError.badVertexDescriptor
|
||||
}
|
||||
attributes[VertexAttribute.position.rawValue].name = MDLVertexAttributePosition
|
||||
attributes[VertexAttribute.texcoord.rawValue].name = MDLVertexAttributeTextureCoordinate
|
||||
|
||||
plane.vertexDescriptor = mdlVertexDescriptor
|
||||
|
||||
return try MTKMesh(mesh:plane, device:device)
|
||||
}
|
||||
|
||||
class func loadTexture(device: MTLDevice,
|
||||
textureName: String) throws -> MTLTexture {
|
||||
/// Load texture data with optimal parameters for sampling
|
||||
|
@ -248,20 +192,20 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
renderEncoder.setVertexBuffer(dynamicUniformBuffer, offset:uniformBufferOffset, index: BufferIndex.uniforms.rawValue)
|
||||
renderEncoder.setFragmentBuffer(dynamicUniformBuffer, offset:uniformBufferOffset, index: BufferIndex.uniforms.rawValue)
|
||||
|
||||
for (index, element) in mesh.vertexDescriptor.layouts.enumerated() {
|
||||
for (index, element) in terrain.mesh.vertexDescriptor.layouts.enumerated() {
|
||||
guard let layout = element as? MDLVertexBufferLayout else {
|
||||
return
|
||||
}
|
||||
|
||||
if layout.stride != 0 {
|
||||
let buffer = mesh.vertexBuffers[index]
|
||||
let buffer = terrain.mesh.vertexBuffers[index]
|
||||
renderEncoder.setVertexBuffer(buffer.buffer, offset:buffer.offset, index: index)
|
||||
}
|
||||
}
|
||||
|
||||
renderEncoder.setFragmentTexture(colorMap, index: TextureIndex.color.rawValue)
|
||||
|
||||
for submesh in mesh.submeshes {
|
||||
for submesh in terrain.mesh.submeshes {
|
||||
renderEncoder.drawIndexedPrimitives(type: submesh.primitiveType,
|
||||
indexCount: submesh.indexCount,
|
||||
indexType: submesh.indexType,
|
||||
|
|
79
Terrain2/Terrain.swift
Normal file
79
Terrain2/Terrain.swift
Normal file
|
@ -0,0 +1,79 @@
|
|||
//
|
||||
// Terrain.swift
|
||||
// Terrain
|
||||
//
|
||||
// Created by Eryn Wells on 11/3/18.
|
||||
// Copyright © 2018 Eryn Wells. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import MetalKit
|
||||
|
||||
class Terrain: NSObject {
|
||||
|
||||
/// Creete a Metal vertex descriptor specifying how vertices will by laid out for input into our render pipeline and how we'll layout our Model IO vertices.
|
||||
class func buildVertexDescriptor() -> MTLVertexDescriptor {
|
||||
let mtlVertexDescriptor = MTLVertexDescriptor()
|
||||
|
||||
mtlVertexDescriptor.attributes[VertexAttribute.position.rawValue].format = MTLVertexFormat.float3
|
||||
mtlVertexDescriptor.attributes[VertexAttribute.position.rawValue].offset = 0
|
||||
mtlVertexDescriptor.attributes[VertexAttribute.position.rawValue].bufferIndex = BufferIndex.meshPositions.rawValue
|
||||
|
||||
mtlVertexDescriptor.attributes[VertexAttribute.texcoord.rawValue].format = MTLVertexFormat.float2
|
||||
mtlVertexDescriptor.attributes[VertexAttribute.texcoord.rawValue].offset = 0
|
||||
mtlVertexDescriptor.attributes[VertexAttribute.texcoord.rawValue].bufferIndex = BufferIndex.meshGenerics.rawValue
|
||||
|
||||
mtlVertexDescriptor.layouts[BufferIndex.meshPositions.rawValue].stride = 12
|
||||
mtlVertexDescriptor.layouts[BufferIndex.meshPositions.rawValue].stepRate = 1
|
||||
mtlVertexDescriptor.layouts[BufferIndex.meshPositions.rawValue].stepFunction = MTLVertexStepFunction.perVertex
|
||||
|
||||
mtlVertexDescriptor.layouts[BufferIndex.meshGenerics.rawValue].stride = 8
|
||||
mtlVertexDescriptor.layouts[BufferIndex.meshGenerics.rawValue].stepRate = 1
|
||||
mtlVertexDescriptor.layouts[BufferIndex.meshGenerics.rawValue].stepFunction = MTLVertexStepFunction.perVertex
|
||||
|
||||
return mtlVertexDescriptor
|
||||
}
|
||||
|
||||
/// Create and condition mesh data to feed into a pipeline using the given vertex descriptor.
|
||||
class func buildMesh(withDimensions dimensions: float2, segments: uint2, device: MTLDevice, vertexDescriptor: MTLVertexDescriptor) throws -> MTKMesh {
|
||||
let metalAllocator = MTKMeshBufferAllocator(device: device)
|
||||
|
||||
let plane = MDLMesh.newPlane(withDimensions: dimensions,
|
||||
segments: segments,
|
||||
geometryType: .triangles,
|
||||
allocator: metalAllocator)
|
||||
|
||||
let mdlVertexDescriptor = MTKModelIOVertexDescriptorFromMetal(vertexDescriptor)
|
||||
|
||||
guard let attributes = mdlVertexDescriptor.attributes as? [MDLVertexAttribute] else {
|
||||
throw RendererError.badVertexDescriptor
|
||||
}
|
||||
attributes[VertexAttribute.position.rawValue].name = MDLVertexAttributePosition
|
||||
attributes[VertexAttribute.texcoord.rawValue].name = MDLVertexAttributeTextureCoordinate
|
||||
|
||||
plane.vertexDescriptor = mdlVertexDescriptor
|
||||
|
||||
return try MTKMesh(mesh:plane, device:device)
|
||||
}
|
||||
|
||||
let dimensions: float2
|
||||
let segments: uint2
|
||||
|
||||
let vertexDescriptor: MTLVertexDescriptor
|
||||
let mesh: MTKMesh
|
||||
|
||||
init?(dimensions dim: float2, segments seg: uint2, device: MTLDevice) {
|
||||
dimensions = dim
|
||||
segments = seg
|
||||
vertexDescriptor = Terrain.buildVertexDescriptor()
|
||||
|
||||
do {
|
||||
mesh = try Terrain.buildMesh(withDimensions: dimensions, segments: segments, device: device, vertexDescriptor: vertexDescriptor)
|
||||
} catch let e {
|
||||
print("Couldn't create mesh. Error: \(e)")
|
||||
return nil
|
||||
}
|
||||
|
||||
super.init()
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue