Lighting issue on rotating object

Hi,

Love this book!

I just finished the section “Diffuse reflection” under “5.9 The dot product”, https://www.raywenderlich.com/books/metal-by-tutorials/v2.0/chapters/5-lighting-fundamentals#toc-chapter-008-anchor-009

I just created a MDLMesh sphere instead of the train.

Build and run, and I see this issue – it seems the sunlight is being rotated on the sphere… cool but not quite right since the sunlight is still as you can see with the yellow lines. What could be the issue here?

Movie here Movie

The sphere is animated like this:

var shaderUniforms = uniforms

rotation = [-(timer * 500).degreesToRadians, -(timer * 500).degreesToRadians, 0]
scale = float3(3 + sin(timer * 30) * 0.25)

shaderUniforms.modelMatrix *= modelMatrix
shaderUniforms.normalMatrix = modelMatrix.upperLeft

renderEncoder.setVertexBytes(&shaderUniforms, length:MemoryLayout<Uniforms>.stride, index:Indexes.uniforms.rawValue)

To try and reproduce your problem, I took the final project of chapter 5, and changed my Model class to load a sphere instead of a model:

    let sphereMesh = MDLMesh(sphereWithExtent: [0.4, 0.4, 0.4], segments: [10, 10], inwardNormals: false, geometryType: .triangles, allocator: allocator)
    let mtkMesh = try! MTKMesh(mesh: sphereMesh, device: Renderer.device)
    let mesh = Mesh(mdlMesh: sphereMesh, mtkMesh: mtkMesh)
    meshes = [mesh]

I then rendered this with your rotation/scale code, and got almost the same result as you.

Lighting issues are generally either normals or confusing world and camera positions. In this case it’s normals, as the sphere’s buffer format is laid out differently from the obj models that we load and would expect the GPU to use its vertex descriptor.

Before assigning pipelineState in Model, I changed the vertex descriptor:

MDLVertexDescriptor.defaultVertexDescriptor = sphereMesh.vertexDescriptor

That changed the vertex descriptor in the pipeline for the GPU, and the sphere now renders correctly.

Screen Shot 2021-02-24 at 5.08.53 pm

You can compare vertex descriptor attributes:

    print("sphere")
    for attribute in sphereMesh.vertexDescriptor.attributes {
      print(attribute)
    }
    print("default")
    for attribute in MDLVertexDescriptor.defaultVertexDescriptor.attributes {
      print(attribute)
    }

The sphere’s vertex descriptor:

Screen Shot 2021-02-24 at 5.10.38 pm

the default vertex descriptor:

Screen Shot 2021-02-24 at 5.11.28 pm

And I’m really glad you’re loving the book :smiley:

Ohh wow that is something I totally did not really see at this point, but from now on I sure will :slight_smile: Thank you so much – loving this!

1 Like