diff --git a/Sources/Voxelotl/Renderer.swift b/Sources/Voxelotl/Renderer.swift index 278f255..cd4ff92 100644 --- a/Sources/Voxelotl/Renderer.swift +++ b/Sources/Voxelotl/Renderer.swift @@ -346,6 +346,8 @@ public class Renderer { var fragUniforms = FragmentShaderUniforms( cameraPosition: camera.position, directionalLight: normalize(.init(0.75, -1, 0.5)), + ambientColor: SIMD4(Color(rgba8888: 0x1F1F1F00).linear), + diffuseColor: SIMD4(Color(rgba8888: 0xEFEFEF00).linear), specularColor: SIMD4(Color(rgba8888: 0x7F7F7F00).linear), specularIntensity: 50) let instances = instances.map { (instance: Instance) -> VertexShaderInstance in diff --git a/Sources/Voxelotl/shader.metal b/Sources/Voxelotl/shader.metal index 30ba338..e0326b0 100644 --- a/Sources/Voxelotl/shader.metal +++ b/Sources/Voxelotl/shader.metal @@ -37,18 +37,26 @@ fragment half4 fragmentMain( constexpr metal::sampler sampler(metal::address::repeat, metal::filter::nearest); auto normal = metal::normalize(in.normal); + // Components for blinn-phong & fresnel auto lightVec = -u.directionalLight; - float lambert = metal::dot(normal, lightVec); - float diffuse = metal::max(0.0, lambert); - auto eyeVector = metal::normalize(u.cameraPosition - in.world); auto halfDir = metal::normalize(lightVec + eyeVector); + + // Compute diffuse component + float lambert = metal::dot(normal, lightVec); + float diffuseAmount = metal::max(0.0, lambert); + half4 diffuse = half4(u.diffuseColor) * diffuseAmount; + + // Compute specular component (blinn-phong) float specularAngle = metal::max(0.0, metal::dot(halfDir, normal)); float specularTerm = metal::pow(specularAngle, u.specularIntensity); - half4 specularAmount = specularTerm * metal::smoothstep(0, 2, lambert * u.specularIntensity); + // smoothstep hack to ensure highlight tapers gracefully at grazing angles + float specularAmount = specularTerm * metal::smoothstep(0, 2, lambert * u.specularIntensity); + half4 specular = half4(u.specularColor) * specularAmount; + // Sample texture & vertex color to get albedo half4 albedo = texture.sample(sampler, in.texCoord); albedo *= in.color; - return albedo * diffuse + half4(u.specularColor) * specularAmount; + return albedo * (half4(u.ambientColor) + diffuse) + specular; } diff --git a/Sources/Voxelotl/shadertypes.h b/Sources/Voxelotl/shadertypes.h index e84a541..25f162d 100644 --- a/Sources/Voxelotl/shadertypes.h +++ b/Sources/Voxelotl/shadertypes.h @@ -38,7 +38,7 @@ typedef NS_ENUM(NSInteger, FragmentShaderInputIdx) { typedef struct { vector_float3 cameraPosition, directionalLight; - vector_float4 specularColor; + vector_float4 ambientColor, diffuseColor, specularColor; float specularIntensity; } FragmentShaderUniforms;