Generated model and lighting (Chapter 5)

Hi everyone,
I have been generating a simple model using my own vertex data (4 vertices and 2 triangles, 6 indices to describe a sheet) and then I have introduced a light source based on material from chapter 5. However I am running into an issue which I think it may have to do with surface normals. As you can see in the following picture lighting does not look right at the joint line of the two triangles. Any tips would be appreciated particularly regarding the addNormal method of Model IO.
Thank you

Here is how I generate my model (basically it has 4 vertices and 6 indices):

let vertexData: [float3] = [
    float3(-0.250, 0.750, 0.50),
    float3(-0.250, -0.750, 0.50),
    float3(0.250, -0.750, 0.50),
    float3( 0.250, 0.750, 0.50)

let indices: [UInt16] = [

let mdlMeshVertexBuffer = allocator.newBuffer(MemoryLayout<float3>.stride * vertexData.count, type: .vertex)
let vertexMap =
vertexMap.bytes.assumingMemoryBound(to: float3.self).assign(from: vertexData, count: vertexData.count)

let indexBuffer = allocator.newBuffer(MemoryLayout<UInt16>.stride * indices.count, type: .index)
let indexMap =
indexMap.bytes.assumingMemoryBound(to: UInt16.self).assign(from: indices, count: indices.count)

let scatteringFunction = MDLScatteringFunction()
let material = MDLMaterial(name: "baseMaterial", scatteringFunction: scatteringFunction)
//material.setTextures(textures: [.baseColor:"gray_material.jpg"])

let submesh = MDLSubmesh(indexBuffer: indexBuffer,
                         indexCount: indices.count,
                         indexType: .uInt16,
                         geometryType: .triangles,
                         material: material)

let vertexDescriptor = MDLVertexDescriptor()
vertexDescriptor.attributes[0] = MDLVertexAttribute(name: MDLVertexAttributePosition,
                                                    format: .float3,
                                                    offset: 0,
                                                    bufferIndex: 0)
vertexDescriptor.layouts[0] = MDLVertexBufferLayout(stride: MemoryLayout<float3>.stride)

let mdlMesh = MDLMesh(vertexBuffer: mdlMeshVertexBuffer,
                      vertexCount: vertexData.count,
                      descriptor: vertexDescriptor,
                      submeshes: [submesh])

mdlMesh.addNormals(withAttributeNamed: MDLVertexAttributeNormal, creaseThreshold: 0.99)

@asalian - perhaps you could zip up your project rather than have me try to reconstruct it, so that I can see the shaders and all :slight_smile: ?

Have you experimented with the crease threshold? The crease threshold, between 0 and 1, determines the smoothness, where 1.0 is unsmoothed.

Thank you and much appreciated. I have enjoyed reading your book very much. I had already tried the crease threshold and no luck. Attached is the project based on code from CH-5. Note that major changes are in the Model.swift where i generate the custom model. (169.3 KB)

I noticed that Model I/O was only generating four normals, so normals 5 & 6 were messed up. (printing out mdlMesh.vertexBuffers[1] in your printFloat3Buffer method)

The vertex descriptor seemed off to me, as it only had Position described, and in the GPU Debugger, you weren’t getting a Vertex Attributes listed under the buffers.

So I added empty normals to your vertexData array and changed the vertex descriptor to reflect the new stride.

This seems to work (I hope :smiley: ). (195.8 KB)

P.S. Congratulations on getting something difficult to work :slight_smile:

Thank you very much Caroline for your help! The documentation of addNormals confused me where it said " ‘vertexDescriptor’ will be updated to reflect the new attribute." (this is the documentation in the code). What you did actually makes sense and taught me couple of other things as well.

1 Like

To be honest, I was a little surprised that it didn’t “just work”. In Chapter 7, Maps and Materials we add tangents and bitangents without having to specifically update the vertex descriptor and setting up a buffer. However, I’ve had trouble creating Model I/O buffers from scratch before, but it was a long time ago and I can’t remember what went wrong.