Work in the normal calculations

This commit is contained in:
Eryn Wells 2018-11-11 21:04:03 -05:00
parent f6f01b6419
commit e62dd1b0f2
3 changed files with 43 additions and 12 deletions

View file

@ -32,7 +32,8 @@ class Renderer: NSObject, MTKViewDelegate {
var depthState: MTLDepthStencilState var depthState: MTLDepthStencilState
var colorMap: MTLTexture var colorMap: MTLTexture
var updateGeometryHeightsPipeline: MTLComputePipelineState let updateGeometryHeightsPipeline: MTLComputePipelineState
let updateGeometryNormalsPipeline: MTLComputePipelineState
let inFlightSemaphore = DispatchSemaphore(value: maxBuffersInFlight) let inFlightSemaphore = DispatchSemaphore(value: maxBuffersInFlight)
let regenerationSemaphore = DispatchSemaphore(value: 1) let regenerationSemaphore = DispatchSemaphore(value: 1)
@ -101,7 +102,8 @@ class Renderer: NSObject, MTKViewDelegate {
} }
do { do {
updateGeometryHeightsPipeline = try Renderer.buildUpdateGeometryPipeline(withDevice: device, library: library) updateGeometryHeightsPipeline = try Renderer.buildUpdateGeometryHeightsPipeline(withDevice: device, library: library)
updateGeometryNormalsPipeline = try Renderer.buildUpdateGeometryNormalsPipeline(withDevice: device, library: library)
} catch { } catch {
print("Unable to create update geometry pipeline. Error: \(error)") print("Unable to create update geometry pipeline. Error: \(error)")
return nil return nil
@ -134,13 +136,20 @@ class Renderer: NSObject, MTKViewDelegate {
return try device.makeRenderPipelineState(descriptor: pipelineDescriptor) return try device.makeRenderPipelineState(descriptor: pipelineDescriptor)
} }
class func buildUpdateGeometryPipeline(withDevice device: MTLDevice, library: MTLLibrary) throws -> MTLComputePipelineState { class func buildUpdateGeometryHeightsPipeline(withDevice device: MTLDevice, library: MTLLibrary) throws -> MTLComputePipelineState {
guard let computeFunction = library.makeFunction(name: "updateGeometryHeights") else { guard let computeFunction = library.makeFunction(name: "updateGeometryHeights") else {
throw RendererError.badComputeFunction throw RendererError.badComputeFunction
} }
return try device.makeComputePipelineState(function: computeFunction) return try device.makeComputePipelineState(function: computeFunction)
} }
class func buildUpdateGeometryNormalsPipeline(withDevice device: MTLDevice, library: MTLLibrary) throws -> MTLComputePipelineState {
guard let computeFunction = library.makeFunction(name: "updateGeometryNormals") else {
throw RendererError.badComputeFunction
}
return try device.makeComputePipelineState(function: computeFunction)
}
class func loadTexture(device: MTLDevice, class func loadTexture(device: MTLDevice,
textureName: String) throws -> MTLTexture { textureName: String) throws -> MTLTexture {
/// Load texture data with optimal parameters for sampling /// Load texture data with optimal parameters for sampling
@ -238,8 +247,9 @@ class Renderer: NSObject, MTKViewDelegate {
didScheduleAlgorithmIteration = true didScheduleAlgorithmIteration = true
} }
if didScheduleAlgorithmIteration || needsGeometryUpdate, let computeEncoder = commandBuffer.makeComputeCommandEncoder() { if didScheduleAlgorithmIteration || needsGeometryUpdate {
print("Scheduling update geometry iteration") if let computeEncoder = commandBuffer.makeComputeCommandEncoder() {
print("Scheduling update geometry heights")
computeEncoder.label = "Geometry Heights Encoder" computeEncoder.label = "Geometry Heights Encoder"
computeEncoder.pushDebugGroup("Update Geometry: Heights") computeEncoder.pushDebugGroup("Update Geometry: Heights")
computeEncoder.setComputePipelineState(updateGeometryHeightsPipeline) computeEncoder.setComputePipelineState(updateGeometryHeightsPipeline)
@ -252,6 +262,23 @@ class Renderer: NSObject, MTKViewDelegate {
computeEncoder.dispatchThreads(MTLSize(width: Int(terrain.segments.x + 1), height: Int(terrain.segments.y + 1), depth: 1), threadsPerThreadgroup: MTLSize(width: 8, height: 8, depth: 1)) computeEncoder.dispatchThreads(MTLSize(width: Int(terrain.segments.x + 1), height: Int(terrain.segments.y + 1), depth: 1), threadsPerThreadgroup: MTLSize(width: 8, height: 8, depth: 1))
computeEncoder.popDebugGroup() computeEncoder.popDebugGroup()
computeEncoder.endEncoding() computeEncoder.endEncoding()
}
if let computeEncoder = commandBuffer.makeComputeCommandEncoder() {
print("Scheduling update geometry normals")
computeEncoder.label = "Geometry Normals Encoder"
computeEncoder.pushDebugGroup("Update Geometry: Normals")
computeEncoder.setComputePipelineState(updateGeometryNormalsPipeline)
let indexBuffer = terrain.mesh.submeshes[0].indexBuffer
computeEncoder.setBuffer(indexBuffer.buffer, offset: indexBuffer.offset, index: GeneratorBufferIndex.indexes.rawValue)
let vertexBuffer = terrain.mesh.vertexBuffers[BufferIndex.meshPositions.rawValue]
computeEncoder.setBuffer(vertexBuffer.buffer, offset: vertexBuffer.offset, index: GeneratorBufferIndex.vertexes.rawValue)
let normalBuffer = terrain.mesh.vertexBuffers[BufferIndex.normals.rawValue]
computeEncoder.setBuffer(normalBuffer.buffer, offset: normalBuffer.offset, index: GeneratorBufferIndex.normals.rawValue)
computeEncoder.dispatchThreads(MTLSize(width: terrain.mesh.vertexCount, height: 1, depth: 1), threadsPerThreadgroup: MTLSize(width: 64, height: 1, depth: 1))
computeEncoder.popDebugGroup()
computeEncoder.endEncoding()
}
} }
/// Delay getting the currentRenderPassDescriptor until we absolutely need it to avoid /// Delay getting the currentRenderPassDescriptor until we absolutely need it to avoid

View file

@ -45,7 +45,8 @@ typedef NS_ENUM(NSInteger, GeneratorBufferIndex) {
GeneratorBufferIndexVertexes = 0, GeneratorBufferIndexVertexes = 0,
GeneratorBufferIndexTexCoords = 1, GeneratorBufferIndexTexCoords = 1,
GeneratorBufferIndexIndexes = 2, GeneratorBufferIndexIndexes = 2,
GeneratorBufferIndexUniforms = 3, GeneratorBufferIndexNormals = 3,
GeneratorBufferIndexUniforms = 4,
}; };
typedef NS_ENUM(NSInteger, GeneratorTextureIndex) { typedef NS_ENUM(NSInteger, GeneratorTextureIndex) {

View file

@ -61,13 +61,16 @@ kernel void updateGeometryHeights(texture2d<float> texture [[texture(GeneratorTe
vertexes[vIdx].y = height.r; vertexes[vIdx].y = height.r;
} }
kernel void updateGeometryNormals(texture2d<float> texture [[texture(GeneratorTextureIndexIn)]], kernel void updateGeometryNormals(constant float3 *vertexes [[buffer(GeneratorBufferIndexVertexes)]],
constant float3 *vertexes [[buffer(GeneratorBufferIndexVertexes)]], constant packed_uint3 *indexes [[buffer(GeneratorBufferIndexIndexes)]],
constant float2 *texCoords [[buffer(GeneratorBufferIndexTexCoords)]], device packed_float3 *normals [[buffer(GeneratorBufferIndexNormals)]],
constant uint *indexes [[buffer(GeneratorBufferIndexIndexes)]], uint tid [[thread_position_in_grid]])
constant Uniforms &uniforms [[buffer(GeneratorBufferIndexUniforms)]],
uint2 tid [[thread_position_in_grid]])
{ {
const uint3 triIdx = indexes[tid];
float3 side1(vertexes[triIdx.y] - vertexes[triIdx.x]);
float3 side2(vertexes[triIdx.y] - vertexes[triIdx.z]);
float3 normal(normalize(cross(side1, side2)));
normals[tid] = normal;
} }
#pragma mark - ZeroGenerator #pragma mark - ZeroGenerator