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].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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue