|
|
|
|
@@ -1,86 +1,227 @@
|
|
|
|
|
const std = @import("std");
|
|
|
|
|
|
|
|
|
|
pub const Color = extern struct {
|
|
|
|
|
vector: Vector,
|
|
|
|
|
pub const ColorU8 = extern struct {
|
|
|
|
|
r: u8,
|
|
|
|
|
g: u8,
|
|
|
|
|
b: u8,
|
|
|
|
|
a: u8,
|
|
|
|
|
|
|
|
|
|
pub const Array = [4]u8;
|
|
|
|
|
pub const Vector = @Vector(4, u8);
|
|
|
|
|
|
|
|
|
|
pub const clear = Color.init(0, 0, 0, 0);
|
|
|
|
|
pub const black = Color.init(0, 0, 0, 255);
|
|
|
|
|
pub const white = Color.init(255, 255, 255, 255);
|
|
|
|
|
pub const clear = ColorU8.init(0, 0, 0, 0);
|
|
|
|
|
pub const black = ColorU8.init(0, 0, 0, 255);
|
|
|
|
|
pub const white = ColorU8.init(255, 255, 255, 255);
|
|
|
|
|
|
|
|
|
|
pub fn init(r: u8, g: u8, b: u8, a: u8) Color {
|
|
|
|
|
return .{ .vector = .{ r, g, b, a } };
|
|
|
|
|
pub inline fn init(r: u8, g: u8, b: u8, a: u8) ColorU8 {
|
|
|
|
|
return .{ .r = r, .g = g, .b = b, .a = a };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn fromFloat(color: ColorFloat) Color {
|
|
|
|
|
const clamped = std.math.clamp(color, @splat(0.0), @splat(1.0));
|
|
|
|
|
const vector = @round(clamped * @as(ColorFloat.Vector, @splat(255.0)));
|
|
|
|
|
pub inline fn initArray(array: Array) ColorU8 {
|
|
|
|
|
return @bitCast(array);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn initVector(vector: Vector) ColorU8 {
|
|
|
|
|
return @bitCast(@as(Array, vector));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn initColorF16(color: ColorF16) ColorU8 {
|
|
|
|
|
const zero: ColorF16.Vector = @splat(0);
|
|
|
|
|
const one: ColorF16.Vector = @splat(1);
|
|
|
|
|
const scale: ColorF16.Vector = @splat(255);
|
|
|
|
|
|
|
|
|
|
const vector = @round(std.math.clamp(color.asVector(), zero, one) * scale);
|
|
|
|
|
return .{
|
|
|
|
|
.vector = .{
|
|
|
|
|
@intFromFloat(vector[0]),
|
|
|
|
|
@intFromFloat(vector[1]),
|
|
|
|
|
@intFromFloat(vector[2]),
|
|
|
|
|
@intFromFloat(vector[3]),
|
|
|
|
|
},
|
|
|
|
|
.r = @intFromFloat(vector[0]),
|
|
|
|
|
.g = @intFromFloat(vector[1]),
|
|
|
|
|
.b = @intFromFloat(vector[2]),
|
|
|
|
|
.a = @intFromFloat(vector[3]),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn initColorF32(color: ColorF32) ColorU8 {
|
|
|
|
|
const zero: ColorF32.Vector = @splat(0);
|
|
|
|
|
const one: ColorF32.Vector = @splat(1);
|
|
|
|
|
const scale: ColorF32.Vector = @splat(255);
|
|
|
|
|
|
|
|
|
|
const vector = @round(std.math.clamp(color.asVector(), zero, one) * scale);
|
|
|
|
|
return .{
|
|
|
|
|
.r = @intFromFloat(vector[0]),
|
|
|
|
|
.g = @intFromFloat(vector[1]),
|
|
|
|
|
.b = @intFromFloat(vector[2]),
|
|
|
|
|
.a = @intFromFloat(vector[3]),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn asArray(self: ColorU8) Array {
|
|
|
|
|
return @bitCast(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn asVector(self: ColorU8) Vector {
|
|
|
|
|
return @as(Array, @bitCast(self));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pub const ColorFloat = extern struct {
|
|
|
|
|
vector: Vector,
|
|
|
|
|
pub const ColorF16 = extern struct {
|
|
|
|
|
r: f16,
|
|
|
|
|
g: f16,
|
|
|
|
|
b: f16,
|
|
|
|
|
a: f16,
|
|
|
|
|
|
|
|
|
|
pub const Vector = @Vector(4, f32);
|
|
|
|
|
pub const Array = [4]f16;
|
|
|
|
|
pub const Vector = @Vector(4, f16);
|
|
|
|
|
|
|
|
|
|
pub const clear = ColorFloat.init(0, 0, 0, 0);
|
|
|
|
|
pub const black = ColorFloat.init(0, 0, 0, 255);
|
|
|
|
|
pub const white = ColorFloat.init(255, 255, 255, 255);
|
|
|
|
|
pub const clear = ColorF16.init(0.0, 0.0, 0.0, 0.0);
|
|
|
|
|
pub const black = ColorF16.init(0.0, 0.0, 0.0, 1.0);
|
|
|
|
|
pub const white = ColorF16.init(1.0, 1.0, 1.0, 1.0);
|
|
|
|
|
|
|
|
|
|
pub inline fn init(r: f32, g: f32, b: f32, a: f32) ColorFloat {
|
|
|
|
|
return .{ .vector = .{ r, g, b, a } };
|
|
|
|
|
pub inline fn init(r: f16, g: f16, b: f16, a: f16) ColorF16 {
|
|
|
|
|
return .{ .r = r, .g = g, .b = b, .a = a };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn fromInteger(color: Color) ColorFloat {
|
|
|
|
|
return .{
|
|
|
|
|
.vector = .{
|
|
|
|
|
@as(f32, @floatFromInt(color.r)) / 255.0,
|
|
|
|
|
@as(f32, @floatFromInt(color.g)) / 255.0,
|
|
|
|
|
@as(f32, @floatFromInt(color.b)) / 255.0,
|
|
|
|
|
@as(f32, @floatFromInt(color.a)) / 255.0,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
pub inline fn initArray(array: Array) ColorF16 {
|
|
|
|
|
return @bitCast(array);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn add(self: ColorFloat, other: ColorFloat) ColorFloat {
|
|
|
|
|
return .{ .vector = self.vector + other.vector };
|
|
|
|
|
pub inline fn initVector(vector: Vector) ColorF16 {
|
|
|
|
|
return @bitCast(@as(Array, vector));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn sub(self: ColorFloat, other: ColorFloat) ColorFloat {
|
|
|
|
|
return .{ .vector = self.vector - other.vector };
|
|
|
|
|
pub inline fn initColorU8(color: ColorU8) ColorF16 {
|
|
|
|
|
const vector = Vector{
|
|
|
|
|
@as(f32, color.r),
|
|
|
|
|
@as(f32, color.g),
|
|
|
|
|
@as(f32, color.b),
|
|
|
|
|
@as(f32, color.a),
|
|
|
|
|
} / @as(Vector, @splat(255.0));
|
|
|
|
|
|
|
|
|
|
return @bitCast(@as(Array, vector));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn mul(self: ColorFloat, other: ColorFloat) ColorFloat {
|
|
|
|
|
return .{ .vector = self.vector * other.vector };
|
|
|
|
|
pub inline fn initColorF32(color: ColorF32) ColorF16 {
|
|
|
|
|
return @bitCast(@as(Array, @as(Vector, @floatCast(color.asVector()))));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn div(self: ColorFloat, other: ColorFloat) ColorFloat {
|
|
|
|
|
return .{ .vector = self.vector / other.vector };
|
|
|
|
|
pub inline fn asArray(self: ColorF16) Array {
|
|
|
|
|
return @bitCast(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn mulScalar(self: ColorFloat, scalar: f32) ColorFloat {
|
|
|
|
|
const vector: Vector = @splat(scalar);
|
|
|
|
|
return .{ .vector = self.vector * vector };
|
|
|
|
|
pub inline fn asVector(self: ColorF16) Vector {
|
|
|
|
|
return @as(Array, @bitCast(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn divScalar(self: ColorFloat, scalar: f32) ColorFloat {
|
|
|
|
|
const vector: Vector = @splat(scalar);
|
|
|
|
|
return .{ .vector = self.vector / vector };
|
|
|
|
|
pub inline fn add(self: ColorF16, other: ColorF16) ColorF16 {
|
|
|
|
|
return .initVector(self.asVector() + other.asVector());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn lerp(self: ColorFloat, other: ColorFloat, t: f32) ColorFloat {
|
|
|
|
|
pub inline fn sub(self: ColorF16, other: ColorF16) ColorF16 {
|
|
|
|
|
return .initVector(self.asVector() - other.asVector());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn mul(self: ColorF16, other: ColorF16) ColorF16 {
|
|
|
|
|
return .initVector(self.asVector() * other.asVector());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn div(self: ColorF16, other: ColorF16) ColorF16 {
|
|
|
|
|
return .initVector(self.asVector() / other.asVector());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn mulScalar(self: ColorF16, scalar: f16) ColorF16 {
|
|
|
|
|
const scalar_vector: Vector = @splat(scalar);
|
|
|
|
|
return .initVector(self.asVector() * scalar_vector);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn divScalar(self: ColorF16, scalar: f16) ColorF16 {
|
|
|
|
|
const scalar_vector: Vector = @splat(scalar);
|
|
|
|
|
return .initVector(self.asVector() / scalar_vector);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn lerp(self: ColorF16, other: ColorF16, t: f16) ColorF16 {
|
|
|
|
|
const s = 1.0 - t;
|
|
|
|
|
const t_vector: Vector = @splat(t);
|
|
|
|
|
const s_vector: Vector = @splat(s);
|
|
|
|
|
return .{ .vector = self * t_vector + other * s_vector };
|
|
|
|
|
return .initVector(self.asVector() * s_vector + other.asVector() * t_vector);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pub const ColorF32 = extern struct {
|
|
|
|
|
r: f32,
|
|
|
|
|
g: f32,
|
|
|
|
|
b: f32,
|
|
|
|
|
a: f32,
|
|
|
|
|
|
|
|
|
|
pub const Array = [4]f32;
|
|
|
|
|
pub const Vector = @Vector(4, f32);
|
|
|
|
|
|
|
|
|
|
pub const clear = ColorF32.init(0.0, 0.0, 0.0, 0.0);
|
|
|
|
|
pub const black = ColorF32.init(0.0, 0.0, 0.0, 1.0);
|
|
|
|
|
pub const white = ColorF32.init(1.0, 1.0, 1.0, 1.0);
|
|
|
|
|
|
|
|
|
|
pub inline fn init(r: f32, g: f32, b: f32, a: f32) ColorF32 {
|
|
|
|
|
return .{ .r = r, .g = g, .b = b, .a = a };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn initArray(array: Array) ColorF32 {
|
|
|
|
|
return @bitCast(array);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn initVector(vector: Vector) ColorF32 {
|
|
|
|
|
return @bitCast(@as(Array, vector));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn initColorU8(color: ColorU8) ColorF32 {
|
|
|
|
|
const vector = Vector{
|
|
|
|
|
@as(f32, color.r),
|
|
|
|
|
@as(f32, color.g),
|
|
|
|
|
@as(f32, color.b),
|
|
|
|
|
@as(f32, color.a),
|
|
|
|
|
} / @as(Vector, @splat(255.0));
|
|
|
|
|
|
|
|
|
|
return @bitCast(@as(Array, vector));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn initColorF16(color: ColorF16) ColorF32 {
|
|
|
|
|
return @bitCast(@as(Array, @as(Vector, @floatCast(color.asVector()))));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn asArray(self: ColorF32) Array {
|
|
|
|
|
return @bitCast(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn asVector(self: ColorF32) Vector {
|
|
|
|
|
return @as(Array, @bitCast(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn add(self: ColorF32, other: ColorF32) ColorF32 {
|
|
|
|
|
return .initVector(self.asVector() + other.asVector());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn sub(self: ColorF32, other: ColorF32) ColorF32 {
|
|
|
|
|
return .initVector(self.asVector() - other.asVector());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn mul(self: ColorF32, other: ColorF32) ColorF32 {
|
|
|
|
|
return .initVector(self.asVector() * other.asVector());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn div(self: ColorF32, other: ColorF32) ColorF32 {
|
|
|
|
|
return .initVector(self.asVector() / other.asVector());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn mulScalar(self: ColorF32, scalar: f32) ColorF32 {
|
|
|
|
|
const scalar_vector: Vector = @splat(scalar);
|
|
|
|
|
return .initVector(self.asVector() * scalar_vector);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn divScalar(self: ColorF32, scalar: f32) ColorF32 {
|
|
|
|
|
const scalar_vector: Vector = @splat(scalar);
|
|
|
|
|
return .initVector(self.asVector() / scalar_vector);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub inline fn lerp(self: ColorF32, other: ColorF32, t: f32) ColorF32 {
|
|
|
|
|
const s = 1.0 - t;
|
|
|
|
|
const t_vector: Vector = @splat(t);
|
|
|
|
|
const s_vector: Vector = @splat(s);
|
|
|
|
|
return .initVector(self.asVector() * s_vector + other.asVector() * t_vector);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|