Get the normals sorted out; enable lighting from multiple lights

This commit is contained in:
Eryn Wells 2018-11-23 08:15:19 -07:00
parent a72309ec09
commit e1ec7701ba
3 changed files with 50 additions and 36 deletions

View file

@ -181,8 +181,20 @@ class Renderer: NSObject, MTKViewDelegate {
}
lights[0].enabled = true
lights[0].position = simd_float4(x: 2, y: 10, z: 2, w: 1)
lights[0].color = simd_float3(0.5, 0.5, 0.3)
lights[0].position = simd_float4(x: -12, y: 5, z: -12, w: 1)
lights[0].color = simd_float3(1, 0.5, 0)
lights[1].enabled = true
lights[1].position = simd_float4(x: 12, y: 5, z: -12, w: 1)
lights[1].color = simd_float3(1, 0, 1)
lights[2].enabled = true
lights[2].position = simd_float4(x: -12, y: 5, z: 12, w: 1)
lights[2].color = simd_float3(0, 1, 1)
lights[3].enabled = true
lights[3].position = simd_float4(x: 12, y: 5, z: 12, w: 1)
lights[3].color = simd_float3(1, 1, 0)
}
private func populateMaterials() {

View file

@ -55,39 +55,41 @@ fragment float4 fragmentShader(ColorInOut in [[stage_in]],
constant Material *materials [[buffer(BufferIndexMaterials)]],
constant Uniforms &uniforms [[buffer(BufferIndexUniforms)]])
{
float4 out;
// Compute the normal at this position.
float3 normal = normalize(uniforms.normalMatrix * in.normal);
// Compute the vector pointing to the light from this position.
float3 lightDirection;
constant Light &light = lights[0];
if (light.position.w == 0.0) {
lightDirection = normalize(light.position.xyz);
} else {
lightDirection = normalize(light.position.xyz / light.position.w - in.eyeCoords);
}
for (int i = 0; i < 4; i++) {
constant Light &light = lights[i];
// Compute the direction of the viewer from this position.
float3 viewDirection = normalize(-in.eyeCoords.xyz);
float4 out;
float lightDirDotNormal = dot(lightDirection, normal);
if (lightDirDotNormal <= 0.0) {
// No color contribution to this pixel.
out = float4(0);
} else {
constant Material &material = materials[0];
// Comput the direction of reflection given the light direction and the normal at this point. Negate it because the vector returned points from the light to this position and we want it from this position toward the light.
float3 reflection = -reflect(lightDirection, normal);
float3 color = lightDirDotNormal * light.color * material.diffuseColor;
float reflectDotViewDir = dot(reflection, viewDirection);
if (reflectDotViewDir > 0.0) {
float factor = pow(reflectDotViewDir, material.specularExponent);
color += factor * material.specularColor * light.color;
float3 lightDirection;
if (light.position.w == 0.0) {
lightDirection = normalize(light.position.xyz);
} else {
lightDirection = normalize(light.position.xyz / light.position.w - in.eyeCoords);
}
// Compute the direction of the viewer from this position.
float3 viewDirection = normalize(-in.eyeCoords.xyz);
float lightDirDotNormal = dot(lightDirection, normal);
if (lightDirDotNormal > 0.0) {
constant Material &material = materials[0];
// Comput the direction of reflection given the light direction and the normal at this point. Negate it because the vector returned points from the light to this position and we want it from this position toward the light.
float3 reflection = -reflect(lightDirection, normal);
float3 color = lightDirDotNormal * light.color * material.diffuseColor;
float reflectDotViewDir = dot(reflection, viewDirection);
if (reflectDotViewDir > 0.0) {
float factor = pow(reflectDotViewDir, material.specularExponent);
color += factor * material.specularColor * light.color;
}
out += float4(color, 1);
}
out = float4(color, 1);
}
return out;
}

View file

@ -74,7 +74,7 @@ kernel void updateGeometryNormals(constant packed_float3 *meshPositions [[buffer
/// *----*----* (2, 2)
///
/// Adding each vector divided by n would be better, but numerical stability
/// isn't low risk here since these vectors are all normalized.
/// is low risk here since these vectors are all normalized.
///
kernel void updateGeometryVertexNormals(constant packed_float3 *meshPositions [[buffer(GeneratorBufferIndexMeshPositions)]],
constant packed_float3 *faceNormals [[buffer(GeneratorBufferIndexFaceNormals)]],
@ -87,13 +87,13 @@ kernel void updateGeometryVertexNormals(constant packed_float3 *meshPositions [[
float3 normal = float3();
uint adjacent = 0;
if (tid.y > 0 && tid.x > 0) {
if (tid.x > 0 && tid.y > 0) {
uint aIndex = 2 * segmentIndex(uint2(tid.x - 1, tid.y - 1), segs) + 1;
normal += faceNormals[aIndex];
adjacent += 1;
}
if (tid.y > 0 && tid.x < segs.x) {
uint segment = segmentIndex(uint2(tid.x, tid.y - 1), segs);
if (tid.x > 0 && tid.y < segs.y) {
uint segment = segmentIndex(uint2(tid.x - 1, tid.y), segs);
uint bIndex = 2 * segment;
uint cIndex = 2 * segment + 1;
normal += faceNormals[bIndex] + faceNormals[cIndex];
@ -104,8 +104,8 @@ kernel void updateGeometryVertexNormals(constant packed_float3 *meshPositions [[
normal += faceNormals[dIndex];
adjacent += 1;
}
if (tid.x > 0 && tid.y < segs.y) {
uint segment = segmentIndex(uint2(tid.x - 1, tid.y), segs);
if (tid.x < segs.x && tid.y > 0) {
uint segment = segmentIndex(uint2(tid.x, tid.y - 1), segs);
uint eIndex = 2 * segment + 1;
uint fIndex = 2 * segment;
normal += faceNormals[eIndex] + faceNormals[fIndex];
@ -114,7 +114,7 @@ kernel void updateGeometryVertexNormals(constant packed_float3 *meshPositions [[
if (adjacent != 0) {
normal = normalize(normal / float(adjacent));
uint idx = segmentIndex(tid, segs);
uint idx = segmentIndex(tid, segs) + 1;
vertexNormals[idx] = normal;
}
}