Get face normals rendering

This commit is contained in:
Eryn Wells 2018-11-20 17:13:31 -07:00
parent f28e6e08df
commit 296af144ce
5 changed files with 90 additions and 41 deletions

View file

@ -320,21 +320,34 @@ class Renderer: NSObject, MTKViewDelegate {
if let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: normalsRenderPassDescriptor) {
renderEncoder.label = "Normals Render Encoder"
renderEncoder.pushDebugGroup("Draw Normals")
renderEncoder.setRenderPipelineState(normalPipelineState)
renderEncoder.setDepthStencilState(depthState)
let vertexBuffer = terrain.mesh.vertexBuffers[BufferIndex.meshPositions.rawValue]
renderEncoder.setVertexBuffer(vertexBuffer.buffer, offset: vertexBuffer.offset, index: BufferIndex.meshPositions.rawValue)
let normalBuffer = terrain.mesh.vertexBuffers[BufferIndex.normals.rawValue]
renderEncoder.setVertexBuffer(normalBuffer.buffer, offset: normalBuffer.offset, index: BufferIndex.normals.rawValue)
renderEncoder.pushDebugGroup("Draw Vertex Normals")
renderEncoder.setVertexBuffer(dynamicUniformBuffer, offset:uniformBufferOffset, index: BufferIndex.uniforms.rawValue)
let vertexBuffer = terrain.mesh.vertexBuffers[BufferIndex.meshPositions.rawValue]
let normalBuffer = terrain.mesh.vertexBuffers[BufferIndex.normals.rawValue]
renderEncoder.setVertexBuffer(vertexBuffer.buffer, offset: vertexBuffer.offset, index: NormalBufferIndex.points.rawValue)
renderEncoder.setVertexBuffer(normalBuffer.buffer, offset: normalBuffer.offset, index: NormalBufferIndex.normals.rawValue)
renderEncoder.setVertexBuffer(dynamicUniformBuffer, offset: uniformBufferOffset, index: NormalBufferIndex.uniforms.rawValue)
renderEncoder.drawPrimitives(type: .line, vertexStart: 0, vertexCount: 2, instanceCount: terrain.mesh.vertexCount)
renderEncoder.popDebugGroup()
renderEncoder.pushDebugGroup("Draw Face Normals")
let faceMidpointsBuffer = terrain.faceMidpointsBuffer
let faceNormalsBuffer = terrain.faceNormalsBuffer
renderEncoder.setVertexBuffer(faceMidpointsBuffer, offset: 0, index: NormalBufferIndex.points.rawValue)
renderEncoder.setVertexBuffer(faceNormalsBuffer, offset: 0, index: NormalBufferIndex.normals.rawValue)
renderEncoder.setVertexBuffer(dynamicUniformBuffer, offset:uniformBufferOffset, index: NormalBufferIndex.uniforms.rawValue)
renderEncoder.drawPrimitives(type: .line, vertexStart: 0, vertexCount: 2, instanceCount: 2 * Int(terrain.segments.x * terrain.segments.y))
renderEncoder.popDebugGroup()
renderEncoder.endEncoding()
}

View file

@ -21,8 +21,7 @@
#include <simd/simd.h>
typedef NS_ENUM(NSInteger, BufferIndex)
{
typedef NS_ENUM(NSInteger, BufferIndex) {
BufferIndexMeshPositions = 0,
BufferIndexNormals = 1,
BufferIndexMeshGenerics = 2,
@ -30,6 +29,12 @@ typedef NS_ENUM(NSInteger, BufferIndex)
BufferIndexUniforms = 4,
};
typedef NS_ENUM(NSInteger, NormalBufferIndex) {
NormalBufferIndexPoints = 0,
NormalBufferIndexNormals = 1,
NormalBufferIndexUniforms = 2,
};
typedef NS_ENUM(NSInteger, VertexAttribute)
{
VertexAttributePosition = 0,
@ -48,7 +53,8 @@ typedef NS_ENUM(NSInteger, GeneratorBufferIndex) {
GeneratorBufferIndexIndexes = 2,
GeneratorBufferIndexNormals = 3,
GeneratorBufferIndexFaceNormals = 4,
GeneratorBufferIndexUniforms = 5,
GeneratorBufferIndexFaceMidpoints = 5,
GeneratorBufferIndexUniforms = 6,
};
typedef NS_ENUM(NSInteger, GeneratorTextureIndex) {

View file

@ -27,19 +27,30 @@ typedef struct
{
float4 position [[position]];
float3 normal;
float4 color;
float2 texCoord;
} ColorInOut;
#pragma mark - Geometry Shaders
vertex ColorInOut vertexShader(Vertex in [[stage_in]],
constant packed_float3 *faceNormals [[buffer(BufferIndexFaceNormals)]],
constant Uniforms &uniforms [[buffer(BufferIndexUniforms)]])
constant float3 *faceNormals [[buffer(BufferIndexFaceNormals)]],
constant Uniforms &uniforms [[buffer(BufferIndexUniforms)]],
uint vid [[vertex_id]])
{
ColorInOut out;
out.position = uniforms.projectionMatrix * uniforms.modelViewMatrix * float4(in.position, 1.0);
out.normal = uniforms.normalMatrix * in.normal;
float4 vertexCoords = float4(in.position, 1.0);
float4 eyeCoords = uniforms.modelViewMatrix * vertexCoords;
out.position = uniforms.projectionMatrix * eyeCoords;
float3 normal = normalize(uniforms.normalMatrix * in.normal);
out.normal = normal;
float3 lightDirection = -eyeCoords.xyz;
float lightDotNormal = dot(normal, lightDirection);
out.color = float4(abs(lightDotNormal) * float3(0.3), 1.0);
out.texCoord = in.texCoord;
return out;
@ -49,20 +60,14 @@ fragment float4 fragmentShader(ColorInOut in [[stage_in]],
constant Uniforms & uniforms [[ buffer(BufferIndexUniforms) ]],
texture2d<half> colorMap [[ texture(TextureIndexColor) ]])
{
constexpr sampler colorSampler(mip_filter::linear,
mag_filter::linear,
min_filter::linear);
half4 colorSample = colorMap.sample(colorSampler, in.texCoord.xy);
return float4(1.0);
return in.color;
}
#pragma mark - Normal Shaders
vertex float4 normalVertexShader(constant packed_float3 *positions [[buffer(BufferIndexMeshPositions)]],
constant packed_float3 *normals [[buffer(BufferIndexNormals)]],
constant Uniforms &uniforms [[buffer(BufferIndexUniforms)]],
vertex float4 normalVertexShader(constant packed_float3 *positions [[buffer(NormalBufferIndexPoints)]],
constant packed_float3 *normals [[buffer(NormalBufferIndexNormals)]],
constant Uniforms &uniforms [[buffer(NormalBufferIndexUniforms)]],
uint instID [[instance_id]],
uint vertID [[vertex_id]])
{
@ -71,7 +76,7 @@ vertex float4 normalVertexShader(constant packed_float3 *positions [[buffer(Buff
{
v += 0.25 * normals[instID];
}
float4 out = uniforms.projectionMatrix * uniforms.modelViewMatrix * float4(v, 1.0);
float4 out = uniforms.projectionMatrix * uniforms.modelViewMatrix * float4(v, 1);
return out;
}

View file

@ -61,16 +61,23 @@ kernel void updateGeometryHeights(texture2d<float> texture [[texture(GeneratorTe
vertexes[vIdx].y = height.r;
}
kernel void updateGeometryNormals(constant float3 *vertexes [[buffer(GeneratorBufferIndexMeshPositions)]],
constant packed_uint3 *indexes [[buffer(GeneratorBufferIndexIndexes)]],
device packed_float3 *normals [[buffer(GeneratorBufferIndexFaceNormals)]],
kernel void updateGeometryNormals(constant packed_float3 *meshPositions [[buffer(GeneratorBufferIndexMeshPositions)]],
constant packed_ushort3 *indexes [[buffer(GeneratorBufferIndexIndexes)]],
device packed_float3 *faceNormals [[buffer(GeneratorBufferIndexFaceNormals)]],
device packed_float3 *faceMidpoints [[buffer(GeneratorBufferIndexFaceMidpoints)]],
uint 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;
const ushort3 triangleIndex = indexes[tid];
const float3 v1 = meshPositions[triangleIndex.x];
const float3 v2 = meshPositions[triangleIndex.y];
const float3 v3 = meshPositions[triangleIndex.z];
float3 side1 = v1 - v2;
float3 side2 = v1 - v3;
float3 normal = normalize(cross(side1, side2));
faceNormals[tid] = normal;
faceMidpoints[tid] = 0.3333333333 * (v1 + v2 + v3);
}
kernel void updateGeometryVertexNormals()

View file

@ -88,6 +88,7 @@ class Terrain: NSObject {
let vertexDescriptor: MTLVertexDescriptor
let mesh: MTKMesh
let faceNormalsBuffer: MTLBuffer
let faceMidpointsBuffer: MTLBuffer
var generator: TerrainGenerator
@ -118,15 +119,23 @@ class Terrain: NSObject {
return nil
}
// A normal is a float 3. Two triangles per segment, x * t segments.
let faceNormalsLength = MemoryLayout<float3>.stride * 2 * Int(segments.x * segments.y)
guard let faceNormalsBuf = device.makeBuffer(length: faceNormalsLength, options: .storageModePrivate) else {
// A normal is a float3. Two triangles per segment, x * t segments.
let faceDataLength = 12 * 2 * Int(segments.x * segments.y)
guard let faceNormalsBuf = device.makeBuffer(length: faceDataLength, options: .storageModeShared) else {
print("Couldn't create buffer for face normals")
return nil
}
faceNormalsBuffer = faceNormalsBuf
guard let faceMidpointsBuf = device.makeBuffer(length: faceDataLength, options: .storageModeShared) else {
print("Couldn't create buffer for face normals")
return nil
}
faceMidpointsBuffer = faceMidpointsBuf
super.init()
populateInitialFaceNormals()
}
func generate(completion: @escaping () -> Void) -> Progress {
@ -134,7 +143,7 @@ class Terrain: NSObject {
generatorQueue.async {
progress.becomeCurrent(withPendingUnitCount: 1)
let _ = self.generator.render(progress: progress)
let heights = self.generator.render(progress: progress)
progress.completedUnitCount += 1
// TODO: Store heights
@ -149,7 +158,7 @@ class Terrain: NSObject {
func scheduleGeometryUpdates(inCommandBuffer commandBuffer: MTLCommandBuffer, uniforms: MTLBuffer, uniformsOffset: Int) {
if let computeEncoder = commandBuffer.makeComputeCommandEncoder() {
print("Scheduling update geometry heights")
//print("Scheduling update geometry heights")
computeEncoder.label = "Geometry Heights Encoder"
computeEncoder.pushDebugGroup("Update Geometry: Heights")
computeEncoder.setComputePipelineState(updateHeightsPipeline)
@ -165,18 +174,27 @@ class Terrain: NSObject {
}
if let computeEncoder = commandBuffer.makeComputeCommandEncoder() {
print("Scheduling update geometry normals")
//print("Scheduling update geometry normals")
computeEncoder.label = "Surface Normals Encoder"
computeEncoder.pushDebugGroup("Update Geometry: Surface Normals")
computeEncoder.setComputePipelineState(updateSurfaceNormalsPipeline)
let indexBuffer = mesh.submeshes[0].indexBuffer
computeEncoder.setBuffer(indexBuffer.buffer, offset: indexBuffer.offset, index: GeneratorBufferIndex.meshPositions.rawValue)
let vertexBuffer = mesh.vertexBuffers[BufferIndex.meshPositions.rawValue]
computeEncoder.setBuffer(vertexBuffer.buffer, offset: vertexBuffer.offset, index: GeneratorBufferIndex.indexes.rawValue)
computeEncoder.setBuffer(indexBuffer.buffer, offset: indexBuffer.offset, index: GeneratorBufferIndex.indexes.rawValue)
let positionsBuffer = mesh.vertexBuffers[BufferIndex.meshPositions.rawValue]
computeEncoder.setBuffer(positionsBuffer.buffer, offset: positionsBuffer.offset, index: GeneratorBufferIndex.meshPositions.rawValue)
computeEncoder.setBuffer(faceNormalsBuffer, offset: 0, index: GeneratorBufferIndex.faceNormals.rawValue)
computeEncoder.setBuffer(faceMidpointsBuffer, offset: 0, index: GeneratorBufferIndex.faceMidpoints.rawValue)
computeEncoder.dispatchThreads(MTLSize(width: 2 * Int(segments.x * segments.y), height: 1, depth: 1), threadsPerThreadgroup: MTLSize(width: 64, height: 1, depth: 1))
computeEncoder.popDebugGroup()
computeEncoder.endEncoding()
}
}
private func populateInitialFaceNormals() {
let normalsCount = 2 * Int(segments.x * segments.y)
let faceNormals = UnsafeMutableRawPointer(faceNormalsBuffer.contents()).bindMemory(to: float3.self, capacity: normalsCount)
for i in 0..<normalsCount {
faceNormals[i] = float3(0, 1, 0)
}
}
}