Get the normals sorted out; enable lighting from multiple lights
This commit is contained in:
parent
a72309ec09
commit
e1ec7701ba
3 changed files with 50 additions and 36 deletions
|
@ -181,8 +181,20 @@ class Renderer: NSObject, MTKViewDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
lights[0].enabled = true
|
lights[0].enabled = true
|
||||||
lights[0].position = simd_float4(x: 2, y: 10, z: 2, w: 1)
|
lights[0].position = simd_float4(x: -12, y: 5, z: -12, w: 1)
|
||||||
lights[0].color = simd_float3(0.5, 0.5, 0.3)
|
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() {
|
private func populateMaterials() {
|
||||||
|
|
|
@ -55,12 +55,16 @@ fragment float4 fragmentShader(ColorInOut in [[stage_in]],
|
||||||
constant Material *materials [[buffer(BufferIndexMaterials)]],
|
constant Material *materials [[buffer(BufferIndexMaterials)]],
|
||||||
constant Uniforms &uniforms [[buffer(BufferIndexUniforms)]])
|
constant Uniforms &uniforms [[buffer(BufferIndexUniforms)]])
|
||||||
{
|
{
|
||||||
|
float4 out;
|
||||||
|
|
||||||
// Compute the normal at this position.
|
// Compute the normal at this position.
|
||||||
float3 normal = normalize(uniforms.normalMatrix * in.normal);
|
float3 normal = normalize(uniforms.normalMatrix * in.normal);
|
||||||
|
|
||||||
// Compute the vector pointing to the light from this position.
|
// Compute the vector pointing to the light from this position.
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
constant Light &light = lights[i];
|
||||||
|
|
||||||
float3 lightDirection;
|
float3 lightDirection;
|
||||||
constant Light &light = lights[0];
|
|
||||||
if (light.position.w == 0.0) {
|
if (light.position.w == 0.0) {
|
||||||
lightDirection = normalize(light.position.xyz);
|
lightDirection = normalize(light.position.xyz);
|
||||||
} else {
|
} else {
|
||||||
|
@ -70,12 +74,9 @@ fragment float4 fragmentShader(ColorInOut in [[stage_in]],
|
||||||
// Compute the direction of the viewer from this position.
|
// Compute the direction of the viewer from this position.
|
||||||
float3 viewDirection = normalize(-in.eyeCoords.xyz);
|
float3 viewDirection = normalize(-in.eyeCoords.xyz);
|
||||||
|
|
||||||
float4 out;
|
|
||||||
float lightDirDotNormal = dot(lightDirection, normal);
|
float lightDirDotNormal = dot(lightDirection, normal);
|
||||||
if (lightDirDotNormal <= 0.0) {
|
if (lightDirDotNormal > 0.0) {
|
||||||
// No color contribution to this pixel.
|
|
||||||
out = float4(0);
|
|
||||||
} else {
|
|
||||||
constant Material &material = materials[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.
|
// 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.
|
||||||
|
@ -87,7 +88,8 @@ fragment float4 fragmentShader(ColorInOut in [[stage_in]],
|
||||||
float factor = pow(reflectDotViewDir, material.specularExponent);
|
float factor = pow(reflectDotViewDir, material.specularExponent);
|
||||||
color += factor * material.specularColor * light.color;
|
color += factor * material.specularColor * light.color;
|
||||||
}
|
}
|
||||||
out = float4(color, 1);
|
out += float4(color, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ kernel void updateGeometryNormals(constant packed_float3 *meshPositions [[buffer
|
||||||
/// *----*----* (2, 2)
|
/// *----*----* (2, 2)
|
||||||
///
|
///
|
||||||
/// Adding each vector divided by n would be better, but numerical stability
|
/// 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)]],
|
kernel void updateGeometryVertexNormals(constant packed_float3 *meshPositions [[buffer(GeneratorBufferIndexMeshPositions)]],
|
||||||
constant packed_float3 *faceNormals [[buffer(GeneratorBufferIndexFaceNormals)]],
|
constant packed_float3 *faceNormals [[buffer(GeneratorBufferIndexFaceNormals)]],
|
||||||
|
@ -87,13 +87,13 @@ kernel void updateGeometryVertexNormals(constant packed_float3 *meshPositions [[
|
||||||
float3 normal = float3();
|
float3 normal = float3();
|
||||||
uint adjacent = 0;
|
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;
|
uint aIndex = 2 * segmentIndex(uint2(tid.x - 1, tid.y - 1), segs) + 1;
|
||||||
normal += faceNormals[aIndex];
|
normal += faceNormals[aIndex];
|
||||||
adjacent += 1;
|
adjacent += 1;
|
||||||
}
|
}
|
||||||
if (tid.y > 0 && tid.x < segs.x) {
|
if (tid.x > 0 && tid.y < segs.y) {
|
||||||
uint segment = segmentIndex(uint2(tid.x, tid.y - 1), segs);
|
uint segment = segmentIndex(uint2(tid.x - 1, tid.y), segs);
|
||||||
uint bIndex = 2 * segment;
|
uint bIndex = 2 * segment;
|
||||||
uint cIndex = 2 * segment + 1;
|
uint cIndex = 2 * segment + 1;
|
||||||
normal += faceNormals[bIndex] + faceNormals[cIndex];
|
normal += faceNormals[bIndex] + faceNormals[cIndex];
|
||||||
|
@ -104,8 +104,8 @@ kernel void updateGeometryVertexNormals(constant packed_float3 *meshPositions [[
|
||||||
normal += faceNormals[dIndex];
|
normal += faceNormals[dIndex];
|
||||||
adjacent += 1;
|
adjacent += 1;
|
||||||
}
|
}
|
||||||
if (tid.x > 0 && tid.y < segs.y) {
|
if (tid.x < segs.x && tid.y > 0) {
|
||||||
uint segment = segmentIndex(uint2(tid.x - 1, tid.y), segs);
|
uint segment = segmentIndex(uint2(tid.x, tid.y - 1), segs);
|
||||||
uint eIndex = 2 * segment + 1;
|
uint eIndex = 2 * segment + 1;
|
||||||
uint fIndex = 2 * segment;
|
uint fIndex = 2 * segment;
|
||||||
normal += faceNormals[eIndex] + faceNormals[fIndex];
|
normal += faceNormals[eIndex] + faceNormals[fIndex];
|
||||||
|
@ -114,7 +114,7 @@ kernel void updateGeometryVertexNormals(constant packed_float3 *meshPositions [[
|
||||||
|
|
||||||
if (adjacent != 0) {
|
if (adjacent != 0) {
|
||||||
normal = normalize(normal / float(adjacent));
|
normal = normalize(normal / float(adjacent));
|
||||||
uint idx = segmentIndex(tid, segs);
|
uint idx = segmentIndex(tid, segs) + 1;
|
||||||
vertexNormals[idx] = normal;
|
vertexNormals[idx] = normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue