They say that getting computer graphics right is all about having the correct number of sign errors. I was scratching my head over the specular calculation for a while since it didn’t seem to match the diagram with the L, N, R, and V vectors. It turns out the calculation is correct but it does reverse 2 of the vectors from how they appear in the diagram, which is why it works. Also, it is probably the teeniest bit more efficient than the way I expected it. In particular, you have…
float3 reflection = reflect(lightDirection, normalDirection);
float3 cameraPosition = normalize(in.worldPosition - fragmentUniforms.cameraPosition);
float specularIntensity = pow(saturate(dot(reflection, cameraPosition)), materialShininess);
specularColor += light.specularColor * materialSpecularColor * specularIntensity;”
This has L facing away from the surface point. Also, this has V facing towards the surface point. The diagram has these reversed. This had me quite confused because just looking at the reflect call in isolation (which computes L - 2(N.L)*N) I was not seeing something that would make sense.
Since both are reversed, it turns out the result is correct. However, to make it match the diagram I would have coded it as…
float3 reflection = reflect(-lightDirection, normalDirection); // negate light direction
float3 cameraPosition = normalize(fragmentUniforms.cameraPosition - in.worldPosition); // reverse subtraction
float specularIntensity = pow(saturate(dot(reflection, cameraPosition)), materialShininess);
specularColor += light.specularColor * materialSpecularColor * specularIntensity;”
Love the book so far though.
~chuck