From f7255c473c8e03a39258da4cac12af8a3fbb53d0 Mon Sep 17 00:00:00 2001 From: a dinosaur Date: Sun, 18 Aug 2024 01:10:25 +1000 Subject: [PATCH] initial lighting --- Sources/Voxelotl/Renderer.swift | 18 ++++++++++++------ Sources/Voxelotl/shader.metal | 16 ++++++++++++---- Sources/Voxelotl/shadertypes.h | 2 ++ 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/Sources/Voxelotl/Renderer.swift b/Sources/Voxelotl/Renderer.swift index 798542f..6f5a254 100644 --- a/Sources/Voxelotl/Renderer.swift +++ b/Sources/Voxelotl/Renderer.swift @@ -344,13 +344,16 @@ public class Renderer { assert(self._encoder != nil, "batch can't be called outside of a frame being rendered") assert(instances.count < 52) - var uniforms = ShaderUniforms(projView: camera.viewProjection) + var uniforms = ShaderUniforms( + projView: camera.viewProjection, + directionalLight: normalize(.init(0.75, -1, 0.5))) let instances = instances.map { (instance: Instance) -> ShaderInstance in - ShaderInstance( - model: - .translate(instance.position) * - matrix_float4x4(instance.rotation) * - .scale(instance.scale), + let model = + .translate(instance.position) * + matrix_float4x4(instance.rotation) * + .scale(instance.scale) + return ShaderInstance( + model: model, normalModel: model.inverse.transpose, color: SIMD4(Color(instance.color))) } @@ -361,6 +364,9 @@ public class Renderer { self._encoder.setVertexBytes(&uniforms, length: MemoryLayout.stride, index: ShaderInputIdx.uniforms.rawValue) + self._encoder.setFragmentBytes(&uniforms, + length: MemoryLayout.stride, + index: ShaderInputIdx.uniforms.rawValue) self._encoder.drawIndexedPrimitives( type: .triangle, diff --git a/Sources/Voxelotl/shader.metal b/Sources/Voxelotl/shader.metal index 5c98a81..4a036fa 100644 --- a/Sources/Voxelotl/shader.metal +++ b/Sources/Voxelotl/shader.metal @@ -4,7 +4,7 @@ struct FragmentInput { float4 position [[position]]; - float4 normal; + float3 normal; float2 texCoord; half4 color; }; @@ -23,16 +23,24 @@ vertex FragmentInput vertexMain( FragmentInput out; out.position = ndc; out.color = half4(i[instanceID].color) / 255.0; - out.normal = vtx[vertexID].normal; + out.normal = (i[instanceID].normalModel * vtx[vertexID].normal).xyz; out.texCoord = vtx[vertexID].texCoord; return out; } fragment half4 fragmentMain( FragmentInput in [[stage_in]], - metal::texture2d texture [[texture(0)]] + metal::texture2d texture [[texture(0)]], + constant ShaderUniforms& u [[buffer(ShaderInputIdxUniforms)]] ) { constexpr metal::sampler sampler(metal::address::repeat, metal::filter::nearest); + auto normal = metal::normalize(in.normal); + + float lambert = metal::dot(normal, -u.directionalLight); + float diffuse = metal::max(0.0, lambert); + half4 albedo = texture.sample(sampler, in.texCoord); - return albedo * in.color; + albedo *= in.color; + + return albedo * diffuse; } diff --git a/Sources/Voxelotl/shadertypes.h b/Sources/Voxelotl/shadertypes.h index 8ba0cf3..45e5d76 100644 --- a/Sources/Voxelotl/shadertypes.h +++ b/Sources/Voxelotl/shadertypes.h @@ -24,11 +24,13 @@ typedef struct { typedef struct { matrix_float4x4 model; + matrix_float4x4 normalModel; vector_uchar4 color; } ShaderInstance; typedef struct { matrix_float4x4 projView; + vector_float3 directionalLight; } ShaderUniforms; #endif//SHADERTYPES_H