Files
CavesOfSwift/Sources/JolkEngine/Colour.swift
2024-05-05 17:01:56 +10:00

96 lines
2.1 KiB
Swift

import SDL2
import HSLuv
public struct Colour: Equatable { let r, g, b, a: Float }
public extension Colour
{
static var zero: Self { .init(r: 0, g: 0, b: 0, a: 0) }
static var black: Self { .init(r: 0, g: 0, b: 0, a: 1) }
static var white: Self { .init(r: 1, g: 1, b: 1, a: 1) }
init(r: Float, g: Float, b: Float)
{
self.init(r: r, g: g, b: b, a: 1.0)
}
init(fromSdl: SDL_Color)
{
self.init(
r: Float(fromSdl.r) / 0xFF,
g: Float(fromSdl.g) / 0xFF,
b: Float(fromSdl.b) / 0xFF,
a: Float(fromSdl.a) / 0xFF)
}
init(fromRgb24: UInt32)
{
self.init(
r: Float((fromRgb24 >> 16) & 0xFF) / 0xFF,
g: Float((fromRgb24 >> 8) & 0xFF) / 0xFF,
b: Float((fromRgb24 >> 0) & 0xFF) / 0xFF,
a: 1)
}
init(fromRgba32: UInt32)
{
self.init(
r: Float((fromRgba32 >> 24) & 0xFF) / 0xFF,
g: Float((fromRgba32 >> 16) & 0xFF) / 0xFF,
b: Float((fromRgba32 >> 8) & 0xFF) / 0xFF,
a: Float((fromRgba32 >> 0) & 0xFF) / 0xFF)
}
func mix(with rhs: Colour, _ amount: Float) -> Colour
{
let x = amount.saturate
return Colour(
r: Float.lerp(r, rhs.r, x),
g: Float.lerp(g, rhs.g, x),
b: Float.lerp(b, rhs.b, x),
a: Float.lerp(a, rhs.a, x))
}
func lighten(by: Double) -> Colour
{
var hue = CGFloat(), sat = CGFloat(), light = CGFloat()
rgbToHsluv(CGFloat(r), CGFloat(g), CGFloat(b), &hue, &sat, &light)
let gamma: CGFloat = 3.0
light = pow((pow(light / 100, 1 / gamma) + CGFloat(by) * 0.8).saturate, gamma) * 100
var newR = CGFloat(), newG = CGFloat(), newB = CGFloat()
hsluvToRgb(hue, sat, light, &newR, &newG, &newB)
return Colour(r: Float(newR), g: Float(newG), b: Float(newB), a: a)
}
var linear: Colour { get
{
Colour(
r: linearFromSrgb(r),
g: linearFromSrgb(g),
b: linearFromSrgb(b),
a: a)
} }
func setAlpha(_ newAlpha: Float) -> Colour
{
return Colour(r: r, g: g, b: b, a: newAlpha)
}
}
@inline(__always) fileprivate func srgbFromLinear(_ x: Float) -> Float
{
return (x < 0.0031308)
? x * 12.92
: 1.055 * pow(x, 1.0 / 2.4) - 0.055
}
@inline(__always) fileprivate func linearFromSrgb(_ x: Float) -> Float
{
return (x < 0.04045)
? x / 12.92
: pow((x + 0.055) / 1.055, 2.4)
}