diff --git a/Sources/Voxelotl/Chunk.swift b/Sources/Voxelotl/Chunk.swift index d0a1bea..87e7793 100644 --- a/Sources/Voxelotl/Chunk.swift +++ b/Sources/Voxelotl/Chunk.swift @@ -123,7 +123,7 @@ public struct Chunk: Hashable { public enum BlockType: Hashable { case air - case solid(_ color: Color) + case solid(_ color: Color) } public struct Block: Hashable { diff --git a/Sources/Voxelotl/Game.swift b/Sources/Voxelotl/Game.swift index 049c038..fbad833 100644 --- a/Sources/Voxelotl/Game.swift +++ b/Sources/Voxelotl/Game.swift @@ -4,13 +4,13 @@ struct Instance { let position: SIMD3 let scale: SIMD3 let rotation: simd_quatf - let color: Color + let color: Color init( position: SIMD3 = .zero, scale: SIMD3 = .one, rotation: simd_quatf = .identity, - color: Color = .white + color: Color = .white ) { self.position = position self.scale = scale diff --git a/Sources/Voxelotl/Renderer/Material.swift b/Sources/Voxelotl/Renderer/Material.swift index 2f1c849..858dfba 100644 --- a/Sources/Voxelotl/Renderer/Material.swift +++ b/Sources/Voxelotl/Renderer/Material.swift @@ -1,7 +1,7 @@ public struct Material { - public var ambient: Color - public var diffuse: Color - public var specular: Color + public var ambient: Color + public var diffuse: Color + public var specular: Color public var gloss: Float } diff --git a/Sources/Voxelotl/Renderer/Mesh.swift b/Sources/Voxelotl/Renderer/Mesh.swift index 4e00b21..0964d28 100644 --- a/Sources/Voxelotl/Renderer/Mesh.swift +++ b/Sources/Voxelotl/Renderer/Mesh.swift @@ -18,6 +18,6 @@ public struct VertexPositionNormalTexcoord: Vertex { public struct VertexPositionNormalColorTexcoord: Vertex { var position: SIMD3 var normal: SIMD3 - var color: SIMD4 + var color: SIMD4 var texCoord: SIMD2 } diff --git a/Sources/Voxelotl/Renderer/Renderer.swift b/Sources/Voxelotl/Renderer/Renderer.swift index 2ff85c1..04869a7 100644 --- a/Sources/Voxelotl/Renderer/Renderer.swift +++ b/Sources/Voxelotl/Renderer/Renderer.swift @@ -141,7 +141,7 @@ public class Renderer { if mesh.vertices.isEmpty || mesh.indices.isEmpty { return nil } let vertices = mesh.vertices.map { - ShaderVertex(position: $0.position, normal: $0.normal, color: $0.color.reinterpretUShort, texCoord: $0.texCoord) + ShaderVertex(position: $0.position, normal: $0.normal, color: $0.color, texCoord: $0.texCoord) } guard let vtxBuffer = self.device.makeBuffer( bytes: vertices, @@ -165,9 +165,9 @@ public class Renderer { func createMesh(_ mesh: Mesh) -> RendererMesh? { if mesh.vertices.isEmpty || mesh.indices.isEmpty { return nil } - let color = Color.white.reinterpretUShort + let color = Color.white let vertices = mesh.vertices.map { - ShaderVertex(position: $0.position, normal: $0.normal, color: color, texCoord: $0.texCoord) + ShaderVertex(position: $0.position, normal: $0.normal, color: SIMD4(color), texCoord: $0.texCoord) } guard let vtxBuffer = self.device.makeBuffer( bytes: vertices, @@ -341,21 +341,21 @@ public class Renderer { } } - func draw(model: matrix_float4x4, color: Color, mesh: RendererMesh, material: Material, environment: Environment, camera: Camera) { + func draw(model: matrix_float4x4, color: Color, mesh: RendererMesh, material: Material, environment: Environment, camera: Camera) { assert(self._encoder != nil, "draw can't be called outside of a frame being rendered") var vertUniforms = VertexShaderUniforms(projView: camera.viewProjection) var fragUniforms = FragmentShaderUniforms( cameraPosition: camera.position, directionalLight: normalize(environment.lightDirection), - ambientColor: material.ambient.reinterpretUShort, - diffuseColor: material.diffuse.reinterpretUShort, - specularColor: material.specular.reinterpretUShort, + ambientColor: SIMD4(material.ambient), + diffuseColor: SIMD4(material.diffuse), + specularColor: SIMD4(material.specular), specularIntensity: material.gloss) var instance = VertexShaderInstance( model: model, normalModel: model.inverse.transpose, - color: color.reinterpretUShort) + color: SIMD4(color)) self._encoder.setCullMode(.init(environment.cullFace)) @@ -386,9 +386,9 @@ public class Renderer { var fragUniforms = FragmentShaderUniforms( cameraPosition: camera.position, directionalLight: normalize(environment.lightDirection), - ambientColor: material.ambient.reinterpretUShort, - diffuseColor: material.diffuse.reinterpretUShort, - specularColor: material.specular.reinterpretUShort, + ambientColor: SIMD4(material.ambient), + diffuseColor: SIMD4(material.diffuse), + specularColor: SIMD4(material.specular), specularIntensity: material.gloss) let numInstances = instances.count @@ -417,7 +417,7 @@ public class Renderer { .scale(instance.scale) data[i] = VertexShaderInstance( model: model, normalModel: model.inverse.transpose, - color: instance.color.reinterpretUShort) + color: SIMD4(instance.color)) } } instanceBuffer.didModifyRange(0.. { - .init(self.r.bitPattern, self.g.bitPattern, self.b.bitPattern, self.a.bitPattern) - } -} -fileprivate extension SIMD4 where Scalar == Float16 { - var reinterpretUShort: SIMD4 { - .init(self.x.bitPattern, self.y.bitPattern, self.z.bitPattern, self.w.bitPattern) - } -} - enum RendererError: Error { case initFailure(_ message: String) case loadFailure(_ message: String) diff --git a/Sources/Voxelotl/WorldGenerator.swift b/Sources/Voxelotl/WorldGenerator.swift index ea1c056..fe3b108 100644 --- a/Sources/Voxelotl/WorldGenerator.swift +++ b/Sources/Voxelotl/WorldGenerator.swift @@ -26,9 +26,9 @@ struct WorldGenerator { + self.noise.get(fpos * 0.30) * 0.23 return if value < threshold { .solid(.init( - hue: Float16(180 + self.noise2.get(fpos * 0.05) * 180), - saturation: Float16(0.5 + self.noise2.get(SIMD4(fpos * 0.05, 4)) * 0.5), - value: Float16(0.5 + self.noise2.get(SIMD4(fpos * 0.05, 9)) * 0.5).lerp(0.5, 1)).linear) + hue: Float(180 + self.noise2.get(fpos * 0.05) * 180), + saturation: Float(0.5 + self.noise2.get(SIMD4(fpos * 0.05, 4)) * 0.5), + value: Float(0.5 + self.noise2.get(SIMD4(fpos * 0.05, 9)) * 0.5).lerp(0.5, 1)).linear) } else { .air } diff --git a/Sources/Voxelotl/shader.metal b/Sources/Voxelotl/shader.metal index 0efb259..4614d17 100644 --- a/Sources/Voxelotl/shader.metal +++ b/Sources/Voxelotl/shader.metal @@ -23,7 +23,7 @@ vertex FragmentInput vertexMain( FragmentInput out; out.position = u.projView * world; out.world = world.xyz; - out.color = vtx[vertexID].color * i[instanceID].color; + out.color = half4(vtx[vertexID].color) * half4(i[instanceID].color); out.normal = (i[instanceID].normalModel * float4(vtx[vertexID].normal, 0)).xyz; out.texCoord = vtx[vertexID].texCoord; return out; @@ -45,18 +45,18 @@ fragment half4 fragmentMain( // Compute diffuse component float lambert = metal::dot(normal, lightVec); float diffuseAmount = metal::max(0.0, lambert); - half4 diffuse = u.diffuseColor * diffuseAmount; + 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); // smoothstep hack to ensure highlight tapers gracefully at grazing angles float specularAmount = specularTerm * metal::smoothstep(0, 2, lambert * u.specularIntensity); - half4 specular = u.specularColor * specularAmount; + half4 specular = half4(u.specularColor) * specularAmount; // Sample texture & vertex color to get albedo half4 albedo = texture.sample(sampler, in.texCoord); - albedo *= in.color; + albedo *= half4(in.color); - return albedo * (u.ambientColor + diffuse) + specular; + return albedo * (half4(u.ambientColor) + diffuse) + specular; } diff --git a/Sources/Voxelotl/shadertypes.h b/Sources/Voxelotl/shadertypes.h index ab16d91..0a9ef3d 100644 --- a/Sources/Voxelotl/shadertypes.h +++ b/Sources/Voxelotl/shadertypes.h @@ -10,13 +10,6 @@ #include -// HACK: allow passing SIMD4 to shader while `simd_half4` is beta -#ifdef __METAL_VERSION__ -typedef half4 color_half4; -#else -typedef simd_ushort4 color_half4; -#endif - typedef NS_ENUM(NSInteger, VertexShaderInputIdx) { VertexShaderInputIdxVertices = 0, VertexShaderInputIdxInstance = 1, @@ -26,14 +19,14 @@ typedef NS_ENUM(NSInteger, VertexShaderInputIdx) { typedef struct { vector_float3 position; vector_float3 normal; - color_half4 color; + vector_float4 color; vector_float2 texCoord; } ShaderVertex; typedef struct { matrix_float4x4 model; matrix_float4x4 normalModel; - color_half4 color; + vector_float4 color; } VertexShaderInstance; typedef struct { @@ -46,7 +39,7 @@ typedef NS_ENUM(NSInteger, FragmentShaderInputIdx) { typedef struct { vector_float3 cameraPosition, directionalLight; - color_half4 ambientColor, diffuseColor, specularColor; + vector_float4 ambientColor, diffuseColor, specularColor; float specularIntensity; } FragmentShaderUniforms;