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..a00f40d 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: color.values, 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: material.ambient.values, + diffuseColor: material.diffuse.values, + specularColor: material.specular.values, specularIntensity: material.gloss) var instance = VertexShaderInstance( model: model, normalModel: model.inverse.transpose, - color: color.reinterpretUShort) + color: color.values) 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: material.ambient.values, + diffuseColor: material.diffuse.values, + specularColor: material.specular.values, 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: instance.color.values) } } instanceBuffer.didModifyRange(0.. { +fileprivate extension Color where T == Float { + var reinterpretUInt: SIMD4 { .init(self.r.bitPattern, self.g.bitPattern, self.b.bitPattern, self.a.bitPattern) } } -fileprivate extension SIMD4 where Scalar == Float16 { - var reinterpretUShort: SIMD4 { +fileprivate extension SIMD4 where Scalar == Float { + var reinterpretUShort: SIMD4 { .init(self.x.bitPattern, self.y.bitPattern, self.z.bitPattern, self.w.bitPattern) } } 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..63bc5c3 100644 --- a/Sources/Voxelotl/shader.metal +++ b/Sources/Voxelotl/shader.metal @@ -7,7 +7,7 @@ struct FragmentInput { float3 world; float3 normal; float2 texCoord; - half4 color; + float4 color; }; vertex FragmentInput vertexMain( @@ -29,7 +29,7 @@ vertex FragmentInput vertexMain( return out; } -fragment half4 fragmentMain( +fragment float4 fragmentMain( FragmentInput in [[stage_in]], metal::texture2d texture [[texture(0)]], constant FragmentShaderUniforms& u [[buffer(FragmentShaderInputIdxUniforms)]] @@ -45,17 +45,17 @@ fragment half4 fragmentMain( // Compute diffuse component float lambert = metal::dot(normal, lightVec); float diffuseAmount = metal::max(0.0, lambert); - half4 diffuse = u.diffuseColor * diffuseAmount; + float4 diffuse = 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; + float4 specular = u.specularColor * specularAmount; // Sample texture & vertex color to get albedo - half4 albedo = texture.sample(sampler, in.texCoord); + float4 albedo = float4(texture.sample(sampler, in.texCoord)); albedo *= in.color; return albedo * (u.ambientColor + diffuse) + specular; diff --git a/Sources/Voxelotl/shadertypes.h b/Sources/Voxelotl/shadertypes.h index ab16d91..63330e6 100644 --- a/Sources/Voxelotl/shadertypes.h +++ b/Sources/Voxelotl/shadertypes.h @@ -10,12 +10,7 @@ #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 simd_float4 color_float4; typedef NS_ENUM(NSInteger, VertexShaderInputIdx) { VertexShaderInputIdxVertices = 0, @@ -26,14 +21,14 @@ typedef NS_ENUM(NSInteger, VertexShaderInputIdx) { typedef struct { vector_float3 position; vector_float3 normal; - color_half4 color; + color_float4 color; vector_float2 texCoord; } ShaderVertex; typedef struct { matrix_float4x4 model; matrix_float4x4 normalModel; - color_half4 color; + color_float4 color; } VertexShaderInstance; typedef struct { @@ -46,7 +41,7 @@ typedef NS_ENUM(NSInteger, FragmentShaderInputIdx) { typedef struct { vector_float3 cameraPosition, directionalLight; - color_half4 ambientColor, diffuseColor, specularColor; + color_float4 ambientColor, diffuseColor, specularColor; float specularIntensity; } FragmentShaderUniforms;