mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
Co-authored-by: Casey <a.roaming.shadow@gmail.com> Co-authored-by: Raeschen <rycoop29@gmail.com>
241 lines
8.7 KiB
Plaintext
241 lines
8.7 KiB
Plaintext
/////////////////////
|
|
// COLOUR MATRICES //
|
|
/////////////////////
|
|
|
|
/* Documenting a couple of potentially useful color matrices here to inspire ideas.
|
|
// Greyscale - indentical to saturation @ 0
|
|
list(LUMA_R,LUMA_R,LUMA_R,0, LUMA_G,LUMA_G,LUMA_G,0, LUMA_B,LUMA_B,LUMA_B,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
// Color inversion
|
|
list(-1,0,0,0, 0,-1,0,0, 0,0,-1,0, 0,0,0,1, 1,1,1,0)
|
|
|
|
// Sepiatone
|
|
list(0.393,0.349,0.272,0, 0.769,0.686,0.534,0, 0.189,0.168,0.131,0, 0,0,0,1, 0,0,0,0)
|
|
*/
|
|
|
|
/// Does nothing.
|
|
/proc/color_matrix_identity()
|
|
return list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
/**
|
|
* Adds/subtracts overall lightness.
|
|
* 0 is identity, 1 makes everything white, -1 makes everything black.
|
|
*/
|
|
/proc/color_matrix_lightness(power)
|
|
return list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, power,power,power,0)
|
|
|
|
/**
|
|
* Changes distance hues have from grey while maintaining the overall lightness. Greys are unaffected.
|
|
* 1 is identity, 0 is greyscale, >1 oversaturates colors.
|
|
*/
|
|
/proc/color_matrix_saturation(value)
|
|
var/inv = 1 - value
|
|
var/R = round(LUMA_R * inv, 0.001)
|
|
var/G = round(LUMA_G * inv, 0.001)
|
|
var/B = round(LUMA_B * inv, 0.001)
|
|
|
|
return list(R + value,R,R,0, G,G + value,G,0, B,B,B + value,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
/**
|
|
* Exxagerates or removes colors.
|
|
*/
|
|
/proc/color_matrix_saturation_percent(percent)
|
|
if(percent == 0)
|
|
return color_matrix_identity()
|
|
percent = clamp(percent, -100, 100)
|
|
if(percent > 0)
|
|
percent *= 3
|
|
var/x = 1 + percent / 100
|
|
var/inv = 1 - x
|
|
var/R = LUMA_R * inv
|
|
var/G = LUMA_G * inv
|
|
var/B = LUMA_B * inv
|
|
|
|
return list(R + x,R,R, G,G + x,G, B,B,B + x)
|
|
|
|
/**
|
|
* Greyscale matrix.
|
|
*/
|
|
/proc/color_matrix_greyscale()
|
|
return list(LUMA_R, LUMA_R, LUMA_R, LUMA_G, LUMA_G, LUMA_G, LUMA_B, LUMA_B, LUMA_B)
|
|
|
|
/**
|
|
* Changes distance colors have from rgb(127,127,127) grey.
|
|
* 1 is identity. 0 makes everything grey >1 blows out colors and greys.
|
|
*/
|
|
/proc/color_matrix_contrast(value)
|
|
var/add = (1 - value) / 2
|
|
return list(value,0,0,0, 0,value,0,0, 0,0,value,0, 0,0,0,1, add,add,add,0)
|
|
|
|
/**
|
|
* Exxagerates or removes brightness.
|
|
*/
|
|
/proc/color_matrix_contrast_percent(percent)
|
|
var/static/list/delta_index = list(
|
|
0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11,
|
|
0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24,
|
|
0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42,
|
|
0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68,
|
|
0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98,
|
|
1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54,
|
|
1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25,
|
|
2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8,
|
|
4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0,
|
|
7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8,
|
|
10.0)
|
|
percent = clamp(percent, -100, 100)
|
|
if(percent == 0)
|
|
return color_matrix_identity()
|
|
|
|
var/x = 0
|
|
if (percent < 0)
|
|
x = 127 + percent / 100 * 127;
|
|
else
|
|
x = percent % 1
|
|
if(x == 0)
|
|
x = delta_index[percent]
|
|
else
|
|
x = delta_index[percent] * (1-x) + delta_index[percent+1] * x//use linear interpolation for more granularity.
|
|
x = x * 127 + 127
|
|
|
|
var/mult = x / 127
|
|
var/add = 0.5 * (127-x) / 255
|
|
return list(mult,0,0, 0,mult,0, 0,0,mult, add,add,add)
|
|
|
|
/**
|
|
* Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting greys.
|
|
* 0 is identity, 120 moves reds to greens, 240 moves reds to blues.
|
|
*/
|
|
//
|
|
//
|
|
/proc/color_matrix_rotate_hue(angle)
|
|
var/sin = sin(angle)
|
|
var/cos = cos(angle)
|
|
var/cos_inv_third = 0.333*(1-cos)
|
|
var/sqrt3_sin = sqrt(3)*sin
|
|
return list(
|
|
round(cos+cos_inv_third, 0.001), round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), 0,
|
|
round(cos_inv_third-sqrt3_sin, 0.001), round(cos+cos_inv_third, 0.001), round(cos_inv_third+sqrt3_sin, 0.001), 0,
|
|
round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), round(cos+cos_inv_third, 0.001), 0,
|
|
0,0,0,1,
|
|
0,0,0,0,
|
|
)
|
|
|
|
/**
|
|
* Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting whites.
|
|
* TODO: Need a version that only affects one color (ie shift red to blue but leave greens and blues alone)
|
|
*/
|
|
/proc/color_matrix_rotation(angle)
|
|
if(angle == 0)
|
|
return color_matrix_identity()
|
|
angle = clamp(angle, -180, 180)
|
|
var/cos = cos(angle)
|
|
var/sin = sin(angle)
|
|
|
|
var/constA = 0.143
|
|
var/constB = 0.140
|
|
var/constC = -0.283
|
|
return list(
|
|
LUMA_R + cos * (1-LUMA_R) + sin * -LUMA_R, LUMA_R + cos * -LUMA_R + sin * constA, LUMA_R + cos * -LUMA_R + sin * -(1-LUMA_R),
|
|
LUMA_G + cos * -LUMA_G + sin * -LUMA_G, LUMA_G + cos * (1-LUMA_G) + sin * constB, LUMA_G + cos * -LUMA_G + sin * LUMA_G,
|
|
LUMA_B + cos * -LUMA_B + sin * (1-LUMA_B), LUMA_B + cos * -LUMA_B + sin * constC, LUMA_B + cos * (1-LUMA_B) + sin * LUMA_B
|
|
)
|
|
|
|
/**
|
|
* These next three rotate values about one axis only.
|
|
* x is the red axis, y is the green axis, z is the blue axis.
|
|
*/
|
|
/proc/color_matrix_rotate_x(angle)
|
|
var/sinval = round(sin(angle), 0.001)
|
|
var/cosval = round(cos(angle), 0.001)
|
|
return list(1,0,0,0, 0,cosval,sinval,0, 0,-sinval,cosval,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
/proc/color_matrix_rotate_y(angle)
|
|
var/sinval = round(sin(angle), 0.001)
|
|
var/cosval = round(cos(angle), 0.001)
|
|
return list(cosval,0,-sinval,0, 0,1,0,0, sinval,0,cosval,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
/proc/color_matrix_rotate_z(angle)
|
|
var/sinval = round(sin(angle), 0.001)
|
|
var/cosval = round(cos(angle), 0.001)
|
|
return list(cosval,sinval,0,0, -sinval,cosval,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
/**
|
|
* Builds a color matrix that transforms the hue, saturation, and value, all in one operation.
|
|
*/
|
|
/proc/color_matrix_hsv(hue, saturation, value)
|
|
hue = clamp(360 - hue, 0, 360)
|
|
|
|
// This is very much a rough approximation of hueshifting. This carries some artifacting, such as negative values that simply shouldn't exist, but it does get the job done, and that's what matters.
|
|
var/cos_a = cos(hue) // These have to be inverted from 360, otherwise the hue's inverted
|
|
var/sin_a = sin(hue)
|
|
var/rot_x = cos_a + (1 - cos_a) / 3
|
|
var/rot_y = (1 - cos_a) / 3 - 0.5774 * sin_a // 0.5774 is sqrt(1/3)
|
|
var/rot_z = (1 - cos_a) / 3 + 0.5774 * sin_a
|
|
|
|
return list(
|
|
round((((1-saturation) * LUMA_R) + (rot_x * saturation)) * value, 0.01), round((((1-saturation) * LUMA_R) + (rot_y * saturation)) * value, 0.01), round((((1-saturation) * LUMA_R) + (rot_z * saturation)) * value, 0.01),
|
|
round((((1-saturation) * LUMA_G) + (rot_z * saturation)) * value, 0.01), round((((1-saturation) * LUMA_G) + (rot_x * saturation)) * value, 0.01), round((((1-saturation) * LUMA_G) + (rot_y * saturation)) * value, 0.01),
|
|
round((((1-saturation) * LUMA_B) + (rot_y * saturation)) * value, 0.01), round((((1-saturation) * LUMA_B) + (rot_z * saturation)) * value, 0.01), round((((1-saturation) * LUMA_B) + (rot_x * saturation)) * value, 0.01),
|
|
0, 0, 0
|
|
)
|
|
|
|
/**
|
|
* Returns a matrix addition of A with B.
|
|
*/
|
|
/proc/color_matrix_add(list/A, list/B)
|
|
if(!istype(A) || !istype(B))
|
|
return color_matrix_identity()
|
|
if(A.len != 20 || B.len != 20)
|
|
return color_matrix_identity()
|
|
var/list/output = list()
|
|
output.len = 20
|
|
for(var/value in 1 to 20)
|
|
output[value] = A[value] + B[value]
|
|
return output
|
|
|
|
/**
|
|
* Returns a matrix multiplication of A with B.
|
|
*/
|
|
/proc/color_matrix_multiply(list/A, list/B)
|
|
if(!istype(A) || !istype(B))
|
|
return color_matrix_identity()
|
|
if(A.len != 20 || B.len != 20)
|
|
return color_matrix_identity()
|
|
var/list/output = list()
|
|
output.len = 20
|
|
var/x = 1
|
|
var/y = 1
|
|
var/offset = 0
|
|
for(y in 1 to 5)
|
|
offset = (y-1)*4
|
|
for(x in 1 to 4)
|
|
output[offset+x] = round(A[offset+1]*B[x] + A[offset+2]*B[x+4] + A[offset+3]*B[x+8] + A[offset+4]*B[x+12]+(y==5?B[x+16]:0), 0.001)
|
|
return output
|
|
|
|
/**
|
|
* Assembles a color matrix, defaulting to identity.
|
|
*/
|
|
/proc/rgb_construct_color_matrix(rr = 1, rg, rb, gr, gg = 1, gb, br, bg, bb = 1, cr, cg, cb)
|
|
return list(rr, rg, rb, gr, gg, gb, br, bg, bb, cr, cg, cb)
|
|
|
|
/**
|
|
* Assembles a color matrix, defaulting to identity.
|
|
*/
|
|
/proc/rgba_construct_color_matrix(rr = 1, rg, rb, ra, gr, gg = 1, gb, ga, br, bg, bb = 1, ba, ar, ag, ab, aa = 1, cr, cg, cb, ca)
|
|
return list(rr, rg, rb, ra, gr, gg, gb, ga, br, bg, bb, ba, ar, ag, ab, aa, cr, cg, cb, ca)
|
|
|
|
/**
|
|
* Constructs a colored greyscale matrix.
|
|
* WARNING: Bad math up ahead.
|
|
*/
|
|
/proc/rgba_auto_greyscale_matrix(rgba_string)
|
|
// process rgb(a)
|
|
var/list/L1 = ReadRGB(rgba_string)
|
|
ASSERT(L1.len)
|
|
if(L1.len == 3)
|
|
return rgba_construct_color_matrix(0.39, 0.39, 0.39, 0, 0.5, 0.5, 0.5, 0, 0.11, 0.11, 0.11, 0, 0, 0, 0, 1, max(-0.5, (L1[1] - 255) / 255), max(-0.5, (L1[2] - 255) / 255), max(-0.5, (L1[3] - 255) / 255), 0)
|
|
else
|
|
// alpha
|
|
return rgba_construct_color_matrix(0.39, 0.39, 0.39, 0, 0.5, 0.5, 0.5, 0, 0.11, 0.11, 0.11, 0, 0, 0, 0, 0, max(-0.5, (L1[1] - 255) / 255), max(-0.5, (L1[2] - 255) / 255), max(-0.5, (L1[3] - 255) / 255), L1[4] / 255)
|