mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-15 18:22:08 -04:00
gamma: switch to wlsunset-style transitions
This commit is contained in:
@@ -2,8 +2,6 @@ package wayland
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/utils"
|
||||
)
|
||||
|
||||
type GammaRamp struct {
|
||||
@@ -12,6 +10,126 @@ type GammaRamp struct {
|
||||
Blue []uint16
|
||||
}
|
||||
|
||||
type rgb struct {
|
||||
r, g, b float64
|
||||
}
|
||||
|
||||
type xyz struct {
|
||||
x, y, z float64
|
||||
}
|
||||
|
||||
func illuminantD(temp int) (float64, float64, bool) {
|
||||
var x float64
|
||||
switch {
|
||||
case temp >= 2500 && temp <= 7000:
|
||||
t := float64(temp)
|
||||
x = 0.244063 + 0.09911e3/t + 2.9678e6/(t*t) - 4.6070e9/(t*t*t)
|
||||
case temp > 7000 && temp <= 25000:
|
||||
t := float64(temp)
|
||||
x = 0.237040 + 0.24748e3/t + 1.9018e6/(t*t) - 2.0064e9/(t*t*t)
|
||||
default:
|
||||
return 0, 0, false
|
||||
}
|
||||
y := -3*(x*x) + 2.870*x - 0.275
|
||||
return x, y, true
|
||||
}
|
||||
|
||||
func planckianLocus(temp int) (float64, float64, bool) {
|
||||
var x, y float64
|
||||
switch {
|
||||
case temp >= 1667 && temp <= 4000:
|
||||
t := float64(temp)
|
||||
x = -0.2661239e9/(t*t*t) - 0.2343589e6/(t*t) + 0.8776956e3/t + 0.179910
|
||||
if temp <= 2222 {
|
||||
y = -1.1064814*(x*x*x) - 1.34811020*(x*x) + 2.18555832*x - 0.20219683
|
||||
} else {
|
||||
y = -0.9549476*(x*x*x) - 1.37418593*(x*x) + 2.09137015*x - 0.16748867
|
||||
}
|
||||
case temp > 4000 && temp < 25000:
|
||||
t := float64(temp)
|
||||
x = -3.0258469e9/(t*t*t) + 2.1070379e6/(t*t) + 0.2226347e3/t + 0.240390
|
||||
y = 3.0817580*(x*x*x) - 5.87338670*(x*x) + 3.75112997*x - 0.37001483
|
||||
default:
|
||||
return 0, 0, false
|
||||
}
|
||||
return x, y, true
|
||||
}
|
||||
|
||||
func srgbGamma(value, gamma float64) float64 {
|
||||
if value <= 0.0031308 {
|
||||
return 12.92 * value
|
||||
}
|
||||
return math.Pow(1.055*value, 1.0/gamma) - 0.055
|
||||
}
|
||||
|
||||
func clamp01(v float64) float64 {
|
||||
switch {
|
||||
case v > 1.0:
|
||||
return 1.0
|
||||
case v < 0.0:
|
||||
return 0.0
|
||||
default:
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func xyzToSRGB(c xyz) rgb {
|
||||
return rgb{
|
||||
r: srgbGamma(clamp01(3.2404542*c.x-1.5371385*c.y-0.4985314*c.z), 2.2),
|
||||
g: srgbGamma(clamp01(-0.9692660*c.x+1.8760108*c.y+0.0415560*c.z), 2.2),
|
||||
b: srgbGamma(clamp01(0.0556434*c.x-0.2040259*c.y+1.0572252*c.z), 2.2),
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeRGB(c *rgb) {
|
||||
maxw := math.Max(c.r, math.Max(c.g, c.b))
|
||||
if maxw > 0 {
|
||||
c.r /= maxw
|
||||
c.g /= maxw
|
||||
c.b /= maxw
|
||||
}
|
||||
}
|
||||
|
||||
func calcWhitepoint(temp int) rgb {
|
||||
if temp == 6500 {
|
||||
return rgb{r: 1.0, g: 1.0, b: 1.0}
|
||||
}
|
||||
|
||||
var wp xyz
|
||||
|
||||
switch {
|
||||
case temp >= 25000:
|
||||
x, y, _ := illuminantD(25000)
|
||||
wp.x = x
|
||||
wp.y = y
|
||||
case temp >= 4000:
|
||||
x, y, _ := illuminantD(temp)
|
||||
wp.x = x
|
||||
wp.y = y
|
||||
case temp >= 2500:
|
||||
x1, y1, _ := illuminantD(temp)
|
||||
x2, y2, _ := planckianLocus(temp)
|
||||
factor := float64(4000-temp) / 1500.0
|
||||
sineFactor := (math.Cos(math.Pi*factor) + 1.0) / 2.0
|
||||
wp.x = x1*sineFactor + x2*(1.0-sineFactor)
|
||||
wp.y = y1*sineFactor + y2*(1.0-sineFactor)
|
||||
default:
|
||||
t := temp
|
||||
if t < 1667 {
|
||||
t = 1667
|
||||
}
|
||||
x, y, _ := planckianLocus(t)
|
||||
wp.x = x
|
||||
wp.y = y
|
||||
}
|
||||
|
||||
wp.z = 1.0 - wp.x - wp.y
|
||||
|
||||
wpRGB := xyzToSRGB(wp)
|
||||
normalizeRGB(&wpRGB)
|
||||
return wpRGB
|
||||
}
|
||||
|
||||
func GenerateGammaRamp(size uint32, temp int, gamma float64) GammaRamp {
|
||||
ramp := GammaRamp{
|
||||
Red: make([]uint16, size),
|
||||
@@ -19,16 +137,13 @@ func GenerateGammaRamp(size uint32, temp int, gamma float64) GammaRamp {
|
||||
Blue: make([]uint16, size),
|
||||
}
|
||||
|
||||
wp := calcWhitepoint(temp)
|
||||
|
||||
for i := uint32(0); i < size; i++ {
|
||||
val := float64(i) / float64(size-1)
|
||||
|
||||
valGamma := math.Pow(val, 1.0/gamma)
|
||||
|
||||
r, g, b := temperatureToRGB(temp)
|
||||
|
||||
ramp.Red[i] = uint16(utils.Clamp(valGamma*r*65535.0, 0, 65535))
|
||||
ramp.Green[i] = uint16(utils.Clamp(valGamma*g*65535.0, 0, 65535))
|
||||
ramp.Blue[i] = uint16(utils.Clamp(valGamma*b*65535.0, 0, 65535))
|
||||
ramp.Red[i] = uint16(clamp01(math.Pow(val*wp.r, 1.0/gamma)) * 65535.0)
|
||||
ramp.Green[i] = uint16(clamp01(math.Pow(val*wp.g, 1.0/gamma)) * 65535.0)
|
||||
ramp.Blue[i] = uint16(clamp01(math.Pow(val*wp.b, 1.0/gamma)) * 65535.0)
|
||||
}
|
||||
|
||||
return ramp
|
||||
@@ -50,39 +165,3 @@ func GenerateIdentityRamp(size uint32) GammaRamp {
|
||||
|
||||
return ramp
|
||||
}
|
||||
|
||||
func temperatureToRGB(temp int) (float64, float64, float64) {
|
||||
tempK := float64(temp) / 100.0
|
||||
|
||||
var r, g, b float64
|
||||
|
||||
if tempK <= 66 {
|
||||
r = 1.0
|
||||
} else {
|
||||
r = tempK - 60
|
||||
r = 329.698727446 * math.Pow(r, -0.1332047592)
|
||||
r = utils.Clamp(r, 0, 255) / 255.0
|
||||
}
|
||||
|
||||
if tempK <= 66 {
|
||||
g = tempK
|
||||
g = 99.4708025861*math.Log(g) - 161.1195681661
|
||||
g = utils.Clamp(g, 0, 255) / 255.0
|
||||
} else {
|
||||
g = tempK - 60
|
||||
g = 288.1221695283 * math.Pow(g, -0.0755148492)
|
||||
g = utils.Clamp(g, 0, 255) / 255.0
|
||||
}
|
||||
|
||||
if tempK >= 66 {
|
||||
b = 1.0
|
||||
} else if tempK <= 19 {
|
||||
b = 0.0
|
||||
} else {
|
||||
b = tempK - 10
|
||||
b = 138.5177312231*math.Log(b) - 305.0447927307
|
||||
b = utils.Clamp(b, 0, 255) / 255.0
|
||||
}
|
||||
|
||||
return r, g, b
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user