Generate terrain on a keypress

This commit is contained in:
Eryn Wells 2018-11-04 14:19:02 -05:00
parent 55a134882d
commit 8ffb0a1cfe
5 changed files with 44 additions and 11 deletions

View file

@ -15,8 +15,10 @@ enum KernelError: Error {
}
protocol Algorithm {
static var name: String { get }
var name: String { get }
var outTexture: MTLTexture { get }
func encode(in encoder: MTLComputeCommandEncoder)
}
class Kernel {
@ -33,10 +35,10 @@ class Kernel {
let textures: [MTLTexture]
var outTexture: MTLTexture {
return textures[indexes.out]
return textures[textureIndexes.out]
}
private(set) var indexes: (`in`: Int, out: Int) = (in: 0, out: 1)
private(set) var textureIndexes: (`in`: Int, out: Int) = (in: 0, out: 1)
init(device: MTLDevice, library: MTLLibrary, functionName: String) throws {
guard let computeFunction = library.makeFunction(name: functionName) else {
@ -56,17 +58,17 @@ class Kernel {
self.textures = textures
}
func encode(in encoder: MTLComputeCommandEncoder, inTexture: MTLTexture?, outTexture: MTLTexture?) {
func encode(in encoder: MTLComputeCommandEncoder) {
encoder.setComputePipelineState(pipeline)
encoder.setTexture(inTexture, index: GeneratorTextureIndex.in.rawValue)
encoder.setTexture(inTexture, index: GeneratorTextureIndex.out.rawValue)
encoder.setTexture(textures[textureIndexes.in], index: textureIndexes.in)
encoder.setTexture(textures[textureIndexes.out], index: textureIndexes.out)
encoder.dispatchThreads(Kernel.textureSize, threadsPerThreadgroup: MTLSize(width: 8, height: 8, depth: 1))
}
}
/// "Compute" zero for every value of the height map.
class ZeroAlgorithm: Kernel, Algorithm {
static let name = "Zero"
let name = "Zero"
init?(device: MTLDevice, library: MTLLibrary) {
do {
@ -80,7 +82,7 @@ class ZeroAlgorithm: Kernel, Algorithm {
/// Randomly generate heights that are independent of all others.
class RandomAlgorithm: Kernel, Algorithm {
static let name = "Random"
let name = "Random"
init?(device: MTLDevice, library: MTLLibrary) {
do {

View file

@ -42,4 +42,23 @@ class GameViewController: NSViewController {
mtkView.delegate = renderer
}
override func viewWillAppear() {
super.viewWillAppear()
view.window?.makeFirstResponder(self)
}
override var acceptsFirstResponder: Bool {
return true
}
override func keyDown(with event: NSEvent) {
print("key down: \(String(describing: event.charactersIgnoringModifiers))")
switch event.charactersIgnoringModifiers {
case .some("n"):
renderer.iterateTerrainAlgorithm = true
default:
super.keyDown(with: event)
}
}
}

View file

@ -45,6 +45,8 @@ class Renderer: NSObject, MTKViewDelegate {
var terrain: Terrain
var iterateTerrainAlgorithm = true
init?(metalKitView: MTKView) {
self.device = metalKitView.device!
self.commandQueue = self.device.makeCommandQueue()!
@ -167,19 +169,28 @@ class Renderer: NSObject, MTKViewDelegate {
if let commandBuffer = commandQueue.makeCommandBuffer() {
let semaphore = inFlightSemaphore
commandBuffer.addCompletedHandler { (_ commandBuffer)-> Swift.Void in
self.iterateTerrainAlgorithm = false
semaphore.signal()
}
self.updateDynamicBufferState()
self.updateGameState()
if iterateTerrainAlgorithm, let computeEncoder = commandBuffer.makeComputeCommandEncoder() {
print("Scheduling terrain generator iteration with \(terrain.algorithm.name) algorithm")
computeEncoder.label = "Generator Encoder"
computeEncoder.pushDebugGroup("Generate Terrain: \(terrain.algorithm.name)")
terrain.algorithm.encode(in: computeEncoder)
computeEncoder.popDebugGroup()
computeEncoder.endEncoding()
}
/// Delay getting the currentRenderPassDescriptor until we absolutely need it to avoid
/// holding onto the drawable and blocking the display pipeline any longer than necessary
let renderPassDescriptor = view.currentRenderPassDescriptor
if let renderPassDescriptor = renderPassDescriptor {
/// Final pass rendering code here
if let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) {
renderEncoder.label = "Primary Render Encoder"

View file

@ -91,7 +91,7 @@ class Terrain: NSObject {
return nil
}
guard let alg = ZeroAlgorithm(device: device, library: library) else {
guard let alg = RandomAlgorithm(device: device, library: library) else {
print("Couldn't create algorithm")
return nil
}

View file

@ -19,5 +19,6 @@ kernel void zeroKernel(texture2d<float, access::write> outTexture [[texture(Gene
kernel void randomKernel(texture2d<float, access::write> outTexture [[texture(GeneratorTextureIndexOut)]],
uint2 tid [[thread_position_in_grid]])
{
float x = 2.0 * M_PI_F * (tid.x / 128.0);
outTexture.write(sin(x), tid);
}