├── .gitattributes ├── LICENSE ├── README.md ├── TetraAutomator.dctl ├── TetraInterp.dctl ├── TetraInterpBlackpoint.dctl └── TetraInterpHSV.dctl /.gitattributes: -------------------------------------------------------------------------------- 1 | *.dctl linguist-language=c 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 calvinsilly, Ember Light, Nick Eason 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Tetra DCTLs with inversion and black point controls. Also a very mediocre pseudo-HSV version. 2 | 3 | Check out the others: 4 | 5 | - https://github.com/calvinsilly/Tetrahedral-Interpolation 6 | - https://www.juanjosalazar.com/color-science 7 | - https://github.com/EmberLightVFX/Tetrahedral-Interpolation-for-Fusion 8 | - https://github.com/xavijulez/Tetrahedral-Interpolation-DCTL 9 | - https://github.com/npeason/Tetra-DCTLOFX 10 | -------------------------------------------------------------------------------- /TetraAutomator.dctl: -------------------------------------------------------------------------------- 1 | // NB: Contained in this file is a SymPy solve of a system of equations from Salazar (2020). 2 | // This file is not implicitly MIT. Please do not try to sell it, modified or not, without 3 | // first contacting those who helped make it. 4 | // 5 | // https://www.juanjosalazar.com/color-science 6 | 7 | DEFINE_UI_PARAMS(g_in_red_r, Input Red R, DCTLUI_VALUE_BOX, 1.0) 8 | DEFINE_UI_PARAMS(g_in_red_g, Input Red G, DCTLUI_VALUE_BOX, 0.0) 9 | DEFINE_UI_PARAMS(g_in_red_b, Input Red B, DCTLUI_VALUE_BOX, 0.0) 10 | DEFINE_UI_PARAMS(g_out_red_r, Output Red R, DCTLUI_VALUE_BOX, 1.0) 11 | DEFINE_UI_PARAMS(g_out_red_g, Output Red G, DCTLUI_VALUE_BOX, 0.0) 12 | DEFINE_UI_PARAMS(g_out_red_b, Output Red B, DCTLUI_VALUE_BOX, 0.0) 13 | 14 | DEFINE_UI_PARAMS(g_in_grn_r, Input Green R, DCTLUI_VALUE_BOX, 0.0) 15 | DEFINE_UI_PARAMS(g_in_grn_g, Input Green G, DCTLUI_VALUE_BOX, 1.0) 16 | DEFINE_UI_PARAMS(g_in_grn_b, Input Green B, DCTLUI_VALUE_BOX, 0.0) 17 | DEFINE_UI_PARAMS(g_out_grn_r, Output Green R, DCTLUI_VALUE_BOX, 0.0) 18 | DEFINE_UI_PARAMS(g_out_grn_g, Output Green G, DCTLUI_VALUE_BOX, 1.0) 19 | DEFINE_UI_PARAMS(g_out_grn_b, Output Green B, DCTLUI_VALUE_BOX, 0.0) 20 | 21 | DEFINE_UI_PARAMS(g_in_blu_r, Input Blue R, DCTLUI_VALUE_BOX, 0.0) 22 | DEFINE_UI_PARAMS(g_in_blu_g, Input Blue G, DCTLUI_VALUE_BOX, 0.0) 23 | DEFINE_UI_PARAMS(g_in_blu_b, Input Blue B, DCTLUI_VALUE_BOX, 1.0) 24 | DEFINE_UI_PARAMS(g_out_blu_r, Output Blue R, DCTLUI_VALUE_BOX, 0.0) 25 | DEFINE_UI_PARAMS(g_out_blu_g, Output Blue G, DCTLUI_VALUE_BOX, 0.0) 26 | DEFINE_UI_PARAMS(g_out_blu_b, Output Blue B, DCTLUI_VALUE_BOX, 1.0) 27 | 28 | DEFINE_UI_PARAMS(g_in_cyn_r, Input Cyan R, DCTLUI_VALUE_BOX, 0.0) 29 | DEFINE_UI_PARAMS(g_in_cyn_g, Input Cyan G, DCTLUI_VALUE_BOX, 1.0) 30 | DEFINE_UI_PARAMS(g_in_cyn_b, Input Cyan B, DCTLUI_VALUE_BOX, 1.0) 31 | DEFINE_UI_PARAMS(g_out_cyn_r, Output Cyan R, DCTLUI_VALUE_BOX, 0.0) 32 | DEFINE_UI_PARAMS(g_out_cyn_g, Output Cyan G, DCTLUI_VALUE_BOX, 1.0) 33 | DEFINE_UI_PARAMS(g_out_cyn_b, Output Cyan B, DCTLUI_VALUE_BOX, 1.0) 34 | 35 | DEFINE_UI_PARAMS(g_in_mag_r, Input Magenta R, DCTLUI_VALUE_BOX, 1.0) 36 | DEFINE_UI_PARAMS(g_in_mag_g, Input Magenta G, DCTLUI_VALUE_BOX, 0.0) 37 | DEFINE_UI_PARAMS(g_in_mag_b, Input Magenta B, DCTLUI_VALUE_BOX, 1.0) 38 | DEFINE_UI_PARAMS(g_out_mag_r, Output Magenta R, DCTLUI_VALUE_BOX, 1.0) 39 | DEFINE_UI_PARAMS(g_out_mag_g, Output Magenta G, DCTLUI_VALUE_BOX, 0.0) 40 | DEFINE_UI_PARAMS(g_out_mag_b, Output Magenta B, DCTLUI_VALUE_BOX, 1.0) 41 | 42 | DEFINE_UI_PARAMS(g_in_yel_r, Input Yellow R, DCTLUI_VALUE_BOX, 1.0) 43 | DEFINE_UI_PARAMS(g_in_yel_g, Input Yellow G, DCTLUI_VALUE_BOX, 1.0) 44 | DEFINE_UI_PARAMS(g_in_yel_b, Input Yellow B, DCTLUI_VALUE_BOX, 0.0) 45 | DEFINE_UI_PARAMS(g_out_yel_r, Output Yellow R, DCTLUI_VALUE_BOX, 1.0) 46 | DEFINE_UI_PARAMS(g_out_yel_g, Output Yellow G, DCTLUI_VALUE_BOX, 1.0) 47 | DEFINE_UI_PARAMS(g_out_yel_b, Output Yellow B, DCTLUI_VALUE_BOX, 0.0) 48 | 49 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) { 50 | float3 red = { 51 | (g_in_red_b*g_in_yel_g - g_in_red_b*g_out_yel_r - g_in_red_g*g_in_yel_b + g_in_red_g*g_out_yel_r + g_in_yel_b*g_out_red_r - g_in_yel_g*g_out_red_r)/(g_in_red_b*g_in_yel_g - g_in_red_b*g_in_yel_r - g_in_red_g*g_in_yel_b + g_in_red_g*g_in_yel_r + g_in_red_r*g_in_yel_b - g_in_red_r*g_in_yel_g), 52 | (g_in_red_b*g_in_yel_g - g_in_red_b*g_out_yel_g - g_in_red_g*g_in_yel_b + g_in_red_g*g_out_yel_g + g_in_yel_b*g_out_red_g - g_in_yel_g*g_out_red_g)/(g_in_red_b*g_in_yel_g - g_in_red_b*g_in_yel_r - g_in_red_g*g_in_yel_b + g_in_red_g*g_in_yel_r + g_in_red_r*g_in_yel_b - g_in_red_r*g_in_yel_g), 53 | (g_in_red_b*g_in_yel_g - g_in_red_b*g_out_yel_b - g_in_red_g*g_in_yel_b + g_in_red_g*g_out_yel_b + g_in_yel_b*g_out_red_b - g_in_yel_g*g_out_red_b)/(g_in_red_b*g_in_yel_g - g_in_red_b*g_in_yel_r - g_in_red_g*g_in_yel_b + g_in_red_g*g_in_yel_r + g_in_red_r*g_in_yel_b - g_in_red_r*g_in_yel_g) 54 | }; 55 | 56 | float3 grn = { 57 | (-g_in_grn_b*g_in_red_g*g_in_yel_r + g_in_grn_b*g_in_red_g*g_out_yel_r + g_in_grn_b*g_in_red_r*g_in_yel_g - g_in_grn_b*g_in_red_r*g_out_yel_r - g_in_grn_b*g_in_yel_g*g_out_red_r + g_in_grn_b*g_in_yel_r*g_out_red_r - g_in_grn_r*g_in_red_b*g_in_yel_g + g_in_grn_r*g_in_red_b*g_in_yel_r + g_in_grn_r*g_in_red_g*g_in_yel_b - g_in_grn_r*g_in_red_g*g_out_yel_r - g_in_grn_r*g_in_red_r*g_in_yel_b + g_in_grn_r*g_in_red_r*g_out_yel_r + g_in_grn_r*g_in_yel_g*g_out_red_r - g_in_grn_r*g_in_yel_r*g_out_red_r + g_in_red_b*g_in_yel_g*g_out_grn_r - g_in_red_b*g_in_yel_r*g_out_grn_r - g_in_red_g*g_in_yel_b*g_out_grn_r + g_in_red_g*g_in_yel_r*g_out_grn_r + g_in_red_r*g_in_yel_b*g_out_grn_r - g_in_red_r*g_in_yel_g*g_out_grn_r)/(g_in_grn_g*g_in_red_b*g_in_yel_g - g_in_grn_g*g_in_red_b*g_in_yel_r - g_in_grn_g*g_in_red_g*g_in_yel_b + g_in_grn_g*g_in_red_g*g_in_yel_r + g_in_grn_g*g_in_red_r*g_in_yel_b - g_in_grn_g*g_in_red_r*g_in_yel_g - g_in_grn_r*g_in_red_b*g_in_yel_g + g_in_grn_r*g_in_red_b*g_in_yel_r + g_in_grn_r*g_in_red_g*g_in_yel_b - g_in_grn_r*g_in_red_g*g_in_yel_r - g_in_grn_r*g_in_red_r*g_in_yel_b + g_in_grn_r*g_in_red_r*g_in_yel_g), 58 | (-g_in_grn_b*g_in_red_g*g_in_yel_r + g_in_grn_b*g_in_red_g*g_out_yel_g + g_in_grn_b*g_in_red_r*g_in_yel_g - g_in_grn_b*g_in_red_r*g_out_yel_g - g_in_grn_b*g_in_yel_g*g_out_red_g + g_in_grn_b*g_in_yel_r*g_out_red_g - g_in_grn_r*g_in_red_b*g_in_yel_g + g_in_grn_r*g_in_red_b*g_in_yel_r + g_in_grn_r*g_in_red_g*g_in_yel_b - g_in_grn_r*g_in_red_g*g_out_yel_g - g_in_grn_r*g_in_red_r*g_in_yel_b + g_in_grn_r*g_in_red_r*g_out_yel_g + g_in_grn_r*g_in_yel_g*g_out_red_g - g_in_grn_r*g_in_yel_r*g_out_red_g + g_in_red_b*g_in_yel_g*g_out_grn_g - g_in_red_b*g_in_yel_r*g_out_grn_g - g_in_red_g*g_in_yel_b*g_out_grn_g + g_in_red_g*g_in_yel_r*g_out_grn_g + g_in_red_r*g_in_yel_b*g_out_grn_g - g_in_red_r*g_in_yel_g*g_out_grn_g)/(g_in_grn_g*g_in_red_b*g_in_yel_g - g_in_grn_g*g_in_red_b*g_in_yel_r - g_in_grn_g*g_in_red_g*g_in_yel_b + g_in_grn_g*g_in_red_g*g_in_yel_r + g_in_grn_g*g_in_red_r*g_in_yel_b - g_in_grn_g*g_in_red_r*g_in_yel_g - g_in_grn_r*g_in_red_b*g_in_yel_g + g_in_grn_r*g_in_red_b*g_in_yel_r + g_in_grn_r*g_in_red_g*g_in_yel_b - g_in_grn_r*g_in_red_g*g_in_yel_r - g_in_grn_r*g_in_red_r*g_in_yel_b + g_in_grn_r*g_in_red_r*g_in_yel_g), 59 | (-g_in_grn_b*g_in_red_g*g_in_yel_r + g_in_grn_b*g_in_red_g*g_out_yel_b + g_in_grn_b*g_in_red_r*g_in_yel_g - g_in_grn_b*g_in_red_r*g_out_yel_b - g_in_grn_b*g_in_yel_g*g_out_red_b + g_in_grn_b*g_in_yel_r*g_out_red_b - g_in_grn_r*g_in_red_b*g_in_yel_g + g_in_grn_r*g_in_red_b*g_in_yel_r + g_in_grn_r*g_in_red_g*g_in_yel_b - g_in_grn_r*g_in_red_g*g_out_yel_b - g_in_grn_r*g_in_red_r*g_in_yel_b + g_in_grn_r*g_in_red_r*g_out_yel_b + g_in_grn_r*g_in_yel_g*g_out_red_b - g_in_grn_r*g_in_yel_r*g_out_red_b + g_in_red_b*g_in_yel_g*g_out_grn_b - g_in_red_b*g_in_yel_r*g_out_grn_b - g_in_red_g*g_in_yel_b*g_out_grn_b + g_in_red_g*g_in_yel_r*g_out_grn_b + g_in_red_r*g_in_yel_b*g_out_grn_b - g_in_red_r*g_in_yel_g*g_out_grn_b)/(g_in_grn_g*g_in_red_b*g_in_yel_g - g_in_grn_g*g_in_red_b*g_in_yel_r - g_in_grn_g*g_in_red_g*g_in_yel_b + g_in_grn_g*g_in_red_g*g_in_yel_r + g_in_grn_g*g_in_red_r*g_in_yel_b - g_in_grn_g*g_in_red_r*g_in_yel_g - g_in_grn_r*g_in_red_b*g_in_yel_g + g_in_grn_r*g_in_red_b*g_in_yel_r + g_in_grn_r*g_in_red_g*g_in_yel_b - g_in_grn_r*g_in_red_g*g_in_yel_r - g_in_grn_r*g_in_red_r*g_in_yel_b + g_in_grn_r*g_in_red_r*g_in_yel_g) 60 | }; 61 | 62 | float3 blu = { 63 | (g_in_blu_g*g_in_cyn_r - g_in_blu_g*g_out_cyn_r - g_in_blu_r*g_in_cyn_g + g_in_blu_r*g_out_cyn_r + g_in_cyn_g*g_out_blu_r - g_in_cyn_r*g_out_blu_r)/(g_in_blu_b*g_in_cyn_g - g_in_blu_b*g_in_cyn_r - g_in_blu_g*g_in_cyn_b + g_in_blu_g*g_in_cyn_r + g_in_blu_r*g_in_cyn_b - g_in_blu_r*g_in_cyn_g), 64 | (g_in_blu_g*g_in_cyn_r - g_in_blu_g*g_out_cyn_g - g_in_blu_r*g_in_cyn_g + g_in_blu_r*g_out_cyn_g + g_in_cyn_g*g_out_blu_g - g_in_cyn_r*g_out_blu_g)/(g_in_blu_b*g_in_cyn_g - g_in_blu_b*g_in_cyn_r - g_in_blu_g*g_in_cyn_b + g_in_blu_g*g_in_cyn_r + g_in_blu_r*g_in_cyn_b - g_in_blu_r*g_in_cyn_g), 65 | (g_in_blu_g*g_in_cyn_r - g_in_blu_g*g_out_cyn_b - g_in_blu_r*g_in_cyn_g + g_in_blu_r*g_out_cyn_b + g_in_cyn_g*g_out_blu_b - g_in_cyn_r*g_out_blu_b)/(g_in_blu_b*g_in_cyn_g - g_in_blu_b*g_in_cyn_r - g_in_blu_g*g_in_cyn_b + g_in_blu_g*g_in_cyn_r + g_in_blu_r*g_in_cyn_b - g_in_blu_r*g_in_cyn_g) 66 | }; 67 | 68 | float3 cyn = { 69 | (-g_in_blu_b*g_in_cyn_r + g_in_blu_b*g_out_cyn_r + g_in_blu_g*g_in_cyn_r - g_in_blu_g*g_out_cyn_r + g_in_blu_r*g_in_cyn_b - g_in_blu_r*g_in_cyn_g - g_in_cyn_b*g_out_blu_r + g_in_cyn_g*g_out_blu_r)/(g_in_blu_b*g_in_cyn_g - g_in_blu_b*g_in_cyn_r - g_in_blu_g*g_in_cyn_b + g_in_blu_g*g_in_cyn_r + g_in_blu_r*g_in_cyn_b - g_in_blu_r*g_in_cyn_g), 70 | (-g_in_blu_b*g_in_cyn_r + g_in_blu_b*g_out_cyn_g + g_in_blu_g*g_in_cyn_r - g_in_blu_g*g_out_cyn_g + g_in_blu_r*g_in_cyn_b - g_in_blu_r*g_in_cyn_g - g_in_cyn_b*g_out_blu_g + g_in_cyn_g*g_out_blu_g)/(g_in_blu_b*g_in_cyn_g - g_in_blu_b*g_in_cyn_r - g_in_blu_g*g_in_cyn_b + g_in_blu_g*g_in_cyn_r + g_in_blu_r*g_in_cyn_b - g_in_blu_r*g_in_cyn_g), 71 | (-g_in_blu_b*g_in_cyn_r + g_in_blu_b*g_out_cyn_b + g_in_blu_g*g_in_cyn_r - g_in_blu_g*g_out_cyn_b + g_in_blu_r*g_in_cyn_b - g_in_blu_r*g_in_cyn_g - g_in_cyn_b*g_out_blu_b + g_in_cyn_g*g_out_blu_b)/(g_in_blu_b*g_in_cyn_g - g_in_blu_b*g_in_cyn_r - g_in_blu_g*g_in_cyn_b + g_in_blu_g*g_in_cyn_r + g_in_blu_r*g_in_cyn_b - g_in_blu_r*g_in_cyn_g) 72 | }; 73 | 74 | float3 mag = { 75 | (g_in_mag_b*g_in_red_b*g_in_yel_g - g_in_mag_b*g_in_red_b*g_out_yel_r - g_in_mag_b*g_in_red_g*g_in_yel_b + g_in_mag_b*g_in_red_g*g_out_yel_r + g_in_mag_b*g_in_yel_b*g_out_red_r - g_in_mag_b*g_in_yel_g*g_out_red_r - g_in_mag_g*g_in_red_b*g_in_yel_g + g_in_mag_g*g_in_red_b*g_in_yel_r + g_in_mag_g*g_in_red_g*g_in_yel_b - g_in_mag_g*g_in_red_g*g_in_yel_r - g_in_mag_g*g_in_red_r*g_in_yel_b + g_in_mag_g*g_in_red_r*g_in_yel_g - g_in_mag_r*g_in_red_b*g_in_yel_g + g_in_mag_r*g_in_red_b*g_out_yel_r + g_in_mag_r*g_in_red_g*g_in_yel_b - g_in_mag_r*g_in_red_g*g_out_yel_r - g_in_mag_r*g_in_yel_b*g_out_red_r + g_in_mag_r*g_in_yel_g*g_out_red_r + g_in_red_b*g_in_yel_g*g_out_mag_r - g_in_red_b*g_in_yel_r*g_out_mag_r - g_in_red_g*g_in_yel_b*g_out_mag_r + g_in_red_g*g_in_yel_r*g_out_mag_r + g_in_red_r*g_in_yel_b*g_out_mag_r - g_in_red_r*g_in_yel_g*g_out_mag_r)/(g_in_mag_b*g_in_red_b*g_in_yel_g - g_in_mag_b*g_in_red_b*g_in_yel_r - g_in_mag_b*g_in_red_g*g_in_yel_b + g_in_mag_b*g_in_red_g*g_in_yel_r + g_in_mag_b*g_in_red_r*g_in_yel_b - g_in_mag_b*g_in_red_r*g_in_yel_g - g_in_mag_g*g_in_red_b*g_in_yel_g + g_in_mag_g*g_in_red_b*g_in_yel_r + g_in_mag_g*g_in_red_g*g_in_yel_b - g_in_mag_g*g_in_red_g*g_in_yel_r - g_in_mag_g*g_in_red_r*g_in_yel_b + g_in_mag_g*g_in_red_r*g_in_yel_g), 76 | (g_in_mag_b*g_in_red_b*g_in_yel_g - g_in_mag_b*g_in_red_b*g_out_yel_g - g_in_mag_b*g_in_red_g*g_in_yel_b + g_in_mag_b*g_in_red_g*g_out_yel_g + g_in_mag_b*g_in_yel_b*g_out_red_g - g_in_mag_b*g_in_yel_g*g_out_red_g - g_in_mag_g*g_in_red_b*g_in_yel_g + g_in_mag_g*g_in_red_b*g_in_yel_r + g_in_mag_g*g_in_red_g*g_in_yel_b - g_in_mag_g*g_in_red_g*g_in_yel_r - g_in_mag_g*g_in_red_r*g_in_yel_b + g_in_mag_g*g_in_red_r*g_in_yel_g - g_in_mag_r*g_in_red_b*g_in_yel_g + g_in_mag_r*g_in_red_b*g_out_yel_g + g_in_mag_r*g_in_red_g*g_in_yel_b - g_in_mag_r*g_in_red_g*g_out_yel_g - g_in_mag_r*g_in_yel_b*g_out_red_g + g_in_mag_r*g_in_yel_g*g_out_red_g + g_in_red_b*g_in_yel_g*g_out_mag_g - g_in_red_b*g_in_yel_r*g_out_mag_g - g_in_red_g*g_in_yel_b*g_out_mag_g + g_in_red_g*g_in_yel_r*g_out_mag_g + g_in_red_r*g_in_yel_b*g_out_mag_g - g_in_red_r*g_in_yel_g*g_out_mag_g)/(g_in_mag_b*g_in_red_b*g_in_yel_g - g_in_mag_b*g_in_red_b*g_in_yel_r - g_in_mag_b*g_in_red_g*g_in_yel_b + g_in_mag_b*g_in_red_g*g_in_yel_r + g_in_mag_b*g_in_red_r*g_in_yel_b - g_in_mag_b*g_in_red_r*g_in_yel_g - g_in_mag_g*g_in_red_b*g_in_yel_g + g_in_mag_g*g_in_red_b*g_in_yel_r + g_in_mag_g*g_in_red_g*g_in_yel_b - g_in_mag_g*g_in_red_g*g_in_yel_r - g_in_mag_g*g_in_red_r*g_in_yel_b + g_in_mag_g*g_in_red_r*g_in_yel_g), 77 | (g_in_mag_b*g_in_red_b*g_in_yel_g - g_in_mag_b*g_in_red_b*g_out_yel_b - g_in_mag_b*g_in_red_g*g_in_yel_b + g_in_mag_b*g_in_red_g*g_out_yel_b + g_in_mag_b*g_in_yel_b*g_out_red_b - g_in_mag_b*g_in_yel_g*g_out_red_b - g_in_mag_g*g_in_red_b*g_in_yel_g + g_in_mag_g*g_in_red_b*g_in_yel_r + g_in_mag_g*g_in_red_g*g_in_yel_b - g_in_mag_g*g_in_red_g*g_in_yel_r - g_in_mag_g*g_in_red_r*g_in_yel_b + g_in_mag_g*g_in_red_r*g_in_yel_g - g_in_mag_r*g_in_red_b*g_in_yel_g + g_in_mag_r*g_in_red_b*g_out_yel_b + g_in_mag_r*g_in_red_g*g_in_yel_b - g_in_mag_r*g_in_red_g*g_out_yel_b - g_in_mag_r*g_in_yel_b*g_out_red_b + g_in_mag_r*g_in_yel_g*g_out_red_b + g_in_red_b*g_in_yel_g*g_out_mag_b - g_in_red_b*g_in_yel_r*g_out_mag_b - g_in_red_g*g_in_yel_b*g_out_mag_b + g_in_red_g*g_in_yel_r*g_out_mag_b + g_in_red_r*g_in_yel_b*g_out_mag_b - g_in_red_r*g_in_yel_g*g_out_mag_b)/(g_in_mag_b*g_in_red_b*g_in_yel_g - g_in_mag_b*g_in_red_b*g_in_yel_r - g_in_mag_b*g_in_red_g*g_in_yel_b + g_in_mag_b*g_in_red_g*g_in_yel_r + g_in_mag_b*g_in_red_r*g_in_yel_b - g_in_mag_b*g_in_red_r*g_in_yel_g - g_in_mag_g*g_in_red_b*g_in_yel_g + g_in_mag_g*g_in_red_b*g_in_yel_r + g_in_mag_g*g_in_red_g*g_in_yel_b - g_in_mag_g*g_in_red_g*g_in_yel_r - g_in_mag_g*g_in_red_r*g_in_yel_b + g_in_mag_g*g_in_red_r*g_in_yel_g) 78 | }; 79 | 80 | float3 yel = { 81 | (g_in_red_b*g_in_yel_g - g_in_red_b*g_in_yel_r - g_in_red_g*g_in_yel_b + g_in_red_g*g_out_yel_r + g_in_red_r*g_in_yel_b - g_in_red_r*g_out_yel_r - g_in_yel_g*g_out_red_r + g_in_yel_r*g_out_red_r)/(g_in_red_b*g_in_yel_g - g_in_red_b*g_in_yel_r - g_in_red_g*g_in_yel_b + g_in_red_g*g_in_yel_r + g_in_red_r*g_in_yel_b - g_in_red_r*g_in_yel_g), 82 | (g_in_red_b*g_in_yel_g - g_in_red_b*g_in_yel_r - g_in_red_g*g_in_yel_b + g_in_red_g*g_out_yel_g + g_in_red_r*g_in_yel_b - g_in_red_r*g_out_yel_g - g_in_yel_g*g_out_red_g + g_in_yel_r*g_out_red_g)/(g_in_red_b*g_in_yel_g - g_in_red_b*g_in_yel_r - g_in_red_g*g_in_yel_b + g_in_red_g*g_in_yel_r + g_in_red_r*g_in_yel_b - g_in_red_r*g_in_yel_g), 83 | (g_in_red_b*g_in_yel_g - g_in_red_b*g_in_yel_r - g_in_red_g*g_in_yel_b + g_in_red_g*g_out_yel_b + g_in_red_r*g_in_yel_b - g_in_red_r*g_out_yel_b - g_in_yel_g*g_out_red_b + g_in_yel_r*g_out_red_b)/(g_in_red_b*g_in_yel_g - g_in_red_b*g_in_yel_r - g_in_red_g*g_in_yel_b + g_in_red_g*g_in_yel_r + g_in_red_r*g_in_yel_b - g_in_red_r*g_in_yel_g) 84 | }; 85 | 86 | float3 ts; 87 | 88 | if (p_R > p_G) { 89 | if (p_G > p_B) { 90 | ts = p_R * red + p_G * (yel - red) + p_B * (1.0f - yel); 91 | } else if (p_R > p_B) { 92 | ts = p_R * red + p_G * (1.0f - mag) + p_B * (mag - red); 93 | } else { 94 | ts = p_R * (mag - blu) + p_G * (1.0f - mag) + p_B * blu; 95 | } 96 | } else { 97 | if (p_B > p_G) { 98 | ts = p_R * (1.0f - cyn) + p_G * (cyn - blu) + p_B * blu; 99 | } else if (p_B > p_R) { 100 | ts = p_R * (1.0f - cyn) + p_G * grn + p_B * (cyn - grn); 101 | } else { 102 | ts = p_R * (yel - grn) + p_G * grn + p_B * (1.0f - yel); 103 | } 104 | } 105 | 106 | return ts; 107 | } 108 | -------------------------------------------------------------------------------- /TetraInterp.dctl: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2021 calvinsilly, Ember Light, Nick Eason 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | // https://github.com/hotgluebanjo 24 | 25 | 26 | // TetraInterp v001 Feb 26, 2018 by Steve Yedlin 27 | // with help from Eric Cameron and Richard Goedeken 28 | 29 | // Tetrahedral interpolation is invertible IF the 30 | // cube corners are not turned inside out. 31 | // For example, as long as cyan is not greener than green. 32 | 33 | DEFINE_UI_PARAMS(RED_R, Red Red, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 34 | DEFINE_UI_PARAMS(RED_G, Red Green, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 35 | DEFINE_UI_PARAMS(RED_B, Red Blue, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 36 | 37 | DEFINE_UI_PARAMS(GRN_R, Green Red, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 38 | DEFINE_UI_PARAMS(GRN_G, Green Green, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 39 | DEFINE_UI_PARAMS(GRN_B, Green Blue, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 40 | 41 | DEFINE_UI_PARAMS(BLU_R, Blue Red, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 42 | DEFINE_UI_PARAMS(BLU_G, Blue Green, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 43 | DEFINE_UI_PARAMS(BLU_B, Blue Blue, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 44 | 45 | DEFINE_UI_PARAMS(CYN_R, Cyan Red, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 46 | DEFINE_UI_PARAMS(CYN_G, Cyan Green, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 47 | DEFINE_UI_PARAMS(CYN_B, Cyan Blue, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 48 | 49 | DEFINE_UI_PARAMS(MAG_R, Magenta Red, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 50 | DEFINE_UI_PARAMS(MAG_G, Magenta Green, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 51 | DEFINE_UI_PARAMS(MAG_B, Magenta Blue, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 52 | 53 | DEFINE_UI_PARAMS(YEL_R, Yellow Red, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 54 | DEFINE_UI_PARAMS(YEL_G, Yellow Green, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 55 | DEFINE_UI_PARAMS(YEL_B, Yellow Blue, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 56 | 57 | DEFINE_UI_PARAMS(INVERT, Invert, DCTLUI_CHECK_BOX, 0) 58 | 59 | __CONSTANT__ float PI_LOCAL = 3.141592653589f; 60 | 61 | // Dennis, please explain yourself. 62 | typedef float float3x3[3][3]; 63 | 64 | __DEVICE__ inline void float3x3_from_float3(float3x3 output, float3 r0, float3 r1, float3 r2) { 65 | output[0][0] = r0.x; 66 | output[0][1] = r0.y; 67 | output[0][2] = r0.z; 68 | output[1][0] = r1.x; 69 | output[1][1] = r1.y; 70 | output[1][2] = r1.z; 71 | output[2][0] = r2.x; 72 | output[2][1] = r2.y; 73 | output[2][2] = r2.z; 74 | } 75 | 76 | __DEVICE__ float determinant_minor(int row_height, int column_width, float3x3 matrix) { 77 | int y1 = row_height == 0 ? 1 : 0; 78 | int y2 = row_height == 2 ? 1 : 2; 79 | 80 | int x1 = column_width == 0 ? 1 : 0; 81 | int x2 = column_width == 2 ? 1 : 2; 82 | 83 | return (matrix[y1][x1] * matrix[y2][x2]) - (matrix[y1][x2] * matrix[y2][x1]); 84 | } 85 | 86 | __DEVICE__ inline float determinant(float3x3 matrix) { 87 | return (matrix[0][0] * determinant_minor(0, 0, matrix)) 88 | - (matrix[0][1] * determinant_minor(0, 1, matrix)) 89 | + (matrix[0][2] * determinant_minor(0, 2, matrix)); 90 | } 91 | 92 | __DEVICE__ void matrix_inverse(float3x3 matrix, float3x3 result) { 93 | float det = determinant(matrix); 94 | 95 | for (int y = 0; y < 3; y++) { 96 | for (int x = 0; x < 3; x++) { 97 | result[y][x] = determinant_minor(x, y, matrix) * (1.0f / det); 98 | if (1 == ((x+y) % 2)) 99 | result[y][x] = -result[y][x]; 100 | } 101 | } 102 | } 103 | 104 | // A function that returns the rotational distance of a point (around the gray diagonal) from red 105 | __DEVICE__ float pt_ang(float3 triplet, float3 corners[6]) { 106 | float3 rc0 = corners[0]; // red corner is the first in the array 107 | float3 tr0 = triplet; 108 | float eps = 1e-6f; // small nudge to avoid what seems to be precision errors 109 | 110 | // missing rotation 111 | float a_ang = PI_LOCAL / 4.0f; 112 | float3 tr1; 113 | tr1.x = tr0.x; 114 | tr1.y = tr0.y * _cosf(a_ang) + tr0.z * _sinf(a_ang); 115 | tr1.z = tr0.y * (-_sinf(a_ang)) + tr0.z * _cosf(a_ang); 116 | float3 rc1; 117 | rc1.x = rc0.x; 118 | rc1.y = rc0.y * _cosf(a_ang) + rc0.z * _sinf(a_ang); 119 | rc1.z = rc0.y * (-_sinf(a_ang)) + rc0.z * _cosf(a_ang); 120 | 121 | // rotate so that gray diagonal is vertical 122 | float b_ang = _atan2f(_sqrtf(2.0f), 1.0f) - PI_LOCAL / 2.0f; 123 | float3 tr2; 124 | tr2.x = tr1.x * _cosf(b_ang) + tr1.y * _sinf(b_ang); 125 | tr2.y = tr1.x * (-_sinf(b_ang)) + tr1.y * _cosf(b_ang); 126 | tr2.z = tr1.z; 127 | float3 rc2; 128 | rc2.x = rc1.x * _cosf(b_ang) + rc1.y * _sinf(b_ang); 129 | rc2.y = rc1.x * (-_sinf(b_ang)) + rc1.y * _cosf(b_ang); 130 | rc2.z = rc1.z; 131 | 132 | // now rotate on the now-vertical gray axis so that red is at -pi rotation angle 133 | float g_ang = atan2(rc2.x, rc2.z) - PI_LOCAL; 134 | float3 tr3; 135 | tr3.x = tr2.x * _cosf(g_ang) + tr2.z * (-_sinf(g_ang)); 136 | tr3.y = tr2.y; 137 | tr3.z = tr2.x * _sinf(g_ang) + tr2.z * _cosf(g_ang); 138 | 139 | return _atan2f(tr3.x - eps, tr3.z); // here's where epsilon is used 140 | } 141 | 142 | // A function that finds which of the 6 tetrahedrons a point is contained in, 143 | // even if the cube has been deformed 144 | __DEVICE__ int tetra_region(float3 rgb, float3 corners[6]) { 145 | float ang = pt_ang(rgb, corners); 146 | float corner_angs[6]; 147 | 148 | for (int i = 0; i < 6; i++) { 149 | corner_angs[i] = pt_ang(corners[i] , corners); 150 | } 151 | 152 | int region = 5; 153 | for (int i = 0; i < 5; i++) { 154 | if (corner_angs[i] <= ang && ang < corner_angs[i+1]) { 155 | region = i; 156 | break; 157 | } 158 | } 159 | 160 | return region; 161 | } 162 | 163 | __DEVICE__ float3 tetra(float3 triplet, float3 corners[6]) { 164 | float r = triplet.x; 165 | float g = triplet.y; 166 | float b = triplet.z; 167 | 168 | float3 wht = make_float3(1.0f, 1.0f, 1.0f); 169 | float3 red = corners[0]; 170 | float3 yel = corners[1]; 171 | float3 grn = corners[2]; 172 | float3 cyn = corners[3]; 173 | float3 blu = corners[4]; 174 | float3 mag = corners[5]; 175 | 176 | if (r > g) { 177 | if (g > b) { 178 | // r>g>b 179 | return r*red + g*(yel-red) + b*(wht-yel); 180 | } else if (r > b) { 181 | // r>b>g 182 | return r*red + g*(wht-mag) + b*(mag-red); 183 | } else { 184 | // b>r>g 185 | return r*(mag-blu) + g*(wht-mag) + b*blu; 186 | } 187 | } else { 188 | if (b > g) { 189 | // b>g>r 190 | return r*(wht-cyn) + g*(cyn-blu) + b*blu; 191 | } else if (b > r) { 192 | // g>b>r 193 | return r*(wht-cyn) + g*grn + b*(cyn-grn); 194 | } else { 195 | // g>r>b 196 | return r*(yel-grn) + g*grn + b*(wht-yel); 197 | } 198 | } 199 | } 200 | 201 | __DEVICE__ float3 inv_tetra(float3 triplet, float3 corners[6]) { 202 | float r = triplet.x; 203 | float g = triplet.y; 204 | float b = triplet.z; 205 | 206 | float3 wht = make_float3(1.0f, 1.0f, 1.0f); 207 | float3 red = corners[0]; 208 | float3 yel = corners[1]; 209 | float3 grn = corners[2]; 210 | float3 cyn = corners[3]; 211 | float3 blu = corners[4]; 212 | float3 mag = corners[5]; 213 | 214 | int region = tetra_region(triplet, corners); 215 | 216 | float3 c_r; 217 | float3 c_g; 218 | float3 c_b; 219 | 220 | switch (region) { 221 | case 0: 222 | // r>g>b 223 | c_r = red; 224 | c_g = yel-red; 225 | c_b = wht-yel; 226 | break; 227 | case 1: 228 | // g>r>b 229 | c_r = yel-grn; 230 | c_g = grn; 231 | c_b = wht-yel; 232 | break; 233 | case 2: 234 | // g>b>r 235 | c_r = wht-cyn; 236 | c_g = grn; 237 | c_b = cyn-grn; 238 | break; 239 | case 3: 240 | // b>g>r 241 | c_r = wht-cyn; 242 | c_g = cyn-blu; 243 | c_b = blu; 244 | break; 245 | case 4: 246 | // b>r>g 247 | c_r = mag-blu; 248 | c_g = wht-mag; 249 | c_b = blu; 250 | break; 251 | default: 252 | // r>g>b 253 | c_r = red; 254 | c_g = wht-mag; 255 | c_b = mag-red; 256 | } 257 | 258 | float3x3 matrix; 259 | float3x3_from_float3(matrix, c_r, c_g, c_b); 260 | 261 | float3x3 inverse; 262 | matrix_inverse(matrix, inverse); 263 | 264 | c_r = make_float3(inverse[0][0], inverse[0][1], inverse[0][2]); 265 | c_g = make_float3(inverse[1][0], inverse[1][1], inverse[1][2]); 266 | c_b = make_float3(inverse[2][0], inverse[2][1], inverse[2][2]); 267 | 268 | return (r * c_r + g * c_g + b * c_b); 269 | } 270 | 271 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) { 272 | float3 rgb = make_float3(p_R, p_G, p_B); 273 | float3 corners[6]; 274 | 275 | corners[0] = make_float3(RED_R, RED_G, RED_B); 276 | corners[1] = make_float3(YEL_R, YEL_G, YEL_B); 277 | corners[2] = make_float3(GRN_R, GRN_G, GRN_B); 278 | corners[3] = make_float3(CYN_R, CYN_G, CYN_B); 279 | corners[4] = make_float3(BLU_R, BLU_G, BLU_B); 280 | corners[5] = make_float3(MAG_R, MAG_G, MAG_B); 281 | 282 | float3 output; 283 | 284 | if (INVERT) { 285 | output = inv_tetra(rgb, corners); 286 | } else { 287 | output = tetra(rgb, corners); 288 | } 289 | 290 | return output; 291 | } 292 | -------------------------------------------------------------------------------- /TetraInterpBlackpoint.dctl: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2021 calvinsilly, Ember Light, Nick Eason 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | // https://github.com/hotgluebanjo 24 | 25 | DEFINE_UI_PARAMS(BLK_R, Black Red, DCTLUI_SLIDER_FLOAT, 0.0, -0.25, 1.0, 0.001) 26 | DEFINE_UI_PARAMS(BLK_G, Black Green, DCTLUI_SLIDER_FLOAT, 0.0, -0.25, 1.0, 0.001) 27 | DEFINE_UI_PARAMS(BLK_B, Black Blue, DCTLUI_SLIDER_FLOAT, 0.0, -0.25, 1.0, 0.001) 28 | 29 | DEFINE_UI_PARAMS(WHT_R, White Red, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 1.25, 0.001) 30 | DEFINE_UI_PARAMS(WHT_G, White Green, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 1.25, 0.001) 31 | DEFINE_UI_PARAMS(WHT_B, White Blue, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 1.25, 0.001) 32 | 33 | DEFINE_UI_PARAMS(RED_R, Red Red, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 34 | DEFINE_UI_PARAMS(RED_G, Red Green, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 35 | DEFINE_UI_PARAMS(RED_B, Red Blue, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 36 | 37 | DEFINE_UI_PARAMS(GRN_R, Green Red, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 38 | DEFINE_UI_PARAMS(GRN_G, Green Green, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 39 | DEFINE_UI_PARAMS(GRN_B, Green Blue, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 40 | 41 | DEFINE_UI_PARAMS(BLU_R, Blue Red, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 42 | DEFINE_UI_PARAMS(BLU_G, Blue Green, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 43 | DEFINE_UI_PARAMS(BLU_B, Blue Blue, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 44 | 45 | DEFINE_UI_PARAMS(CYN_R, Cyan Red, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 46 | DEFINE_UI_PARAMS(CYN_G, Cyan Green, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 47 | DEFINE_UI_PARAMS(CYN_B, Cyan Blue, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 48 | 49 | DEFINE_UI_PARAMS(MAG_R, Magenta Red, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 50 | DEFINE_UI_PARAMS(MAG_G, Magenta Green, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 51 | DEFINE_UI_PARAMS(MAG_B, Magenta Blue, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 52 | 53 | DEFINE_UI_PARAMS(YEL_R, Yellow Red, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 54 | DEFINE_UI_PARAMS(YEL_G, Yellow Green, DCTLUI_SLIDER_FLOAT, 1.0, -1.0, 3.0, 0.001) 55 | DEFINE_UI_PARAMS(YEL_B, Yellow Blue, DCTLUI_SLIDER_FLOAT, 0.0, -2.0, 2.0, 0.001) 56 | 57 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) { 58 | float3 rgb; 59 | 60 | float3 blk = make_float3(BLK_R, BLK_G, BLK_B); 61 | float3 wht = make_float3(WHT_R, WHT_G, WHT_B); 62 | float3 red = make_float3(RED_R, RED_G, RED_B); 63 | float3 grn = make_float3(GRN_R, GRN_G, GRN_B); 64 | float3 blu = make_float3(BLU_R, BLU_G, BLU_B); 65 | float3 cyn = make_float3(CYN_R, CYN_G, CYN_B); 66 | float3 mag = make_float3(MAG_R, MAG_G, MAG_B); 67 | float3 yel = make_float3(YEL_R, YEL_G, YEL_B); 68 | 69 | if (p_R > p_G) { 70 | if (p_G > p_B) { 71 | rgb = p_R * (red - blk) + blk + p_G * (yel - red) + p_B * (wht - yel); 72 | } else if (p_R > p_B) { 73 | rgb = p_R * (red - blk) + blk + p_G * (wht - mag) + p_B * (mag - red); 74 | } else { 75 | rgb = p_R * (mag - blu) + p_G * (wht - mag) + p_B * (blu - blk) + blk; 76 | } 77 | } else { 78 | if (p_B > p_G) { 79 | rgb = p_R * (wht - cyn) + p_G * (cyn - blu) + p_B * (blu - blk) + blk; 80 | } else if (p_B > p_R) { 81 | rgb = p_R * (wht - cyn) + p_G * (grn - blk) + blk + p_B * (cyn - grn); 82 | } else { 83 | rgb = p_R * (yel - grn) + p_G * (grn - blk) + blk + p_B * (wht - yel); 84 | } 85 | } 86 | 87 | return rgb; 88 | } 89 | -------------------------------------------------------------------------------- /TetraInterpHSV.dctl: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2021 calvinsilly, Ember Light, Nick Eason 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | // https://github.com/hotgluebanjo 24 | 25 | DEFINE_UI_PARAMS(BLK_RGB, Black, DCTLUI_SLIDER_FLOAT, 0.0, -0.25, 1.0, 0.001) 26 | DEFINE_UI_PARAMS(WHT_RGB, White, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 1.25, 0.001) 27 | 28 | DEFINE_UI_PARAMS(RED_HUE, Red Hue, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 29 | DEFINE_UI_PARAMS(RED_SAT, Red Sat, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 30 | DEFINE_UI_PARAMS(RED_VAL, Red Value, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 31 | 32 | DEFINE_UI_PARAMS(GRN_HUE, Green Hue, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 33 | DEFINE_UI_PARAMS(GRN_SAT, Green Sat, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 34 | DEFINE_UI_PARAMS(GRN_VAL, Green Value, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 35 | 36 | DEFINE_UI_PARAMS(BLU_HUE, Blue Hue, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 37 | DEFINE_UI_PARAMS(BLU_SAT, Blue Sat, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 38 | DEFINE_UI_PARAMS(BLU_VAL, Blue Value, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 39 | 40 | DEFINE_UI_PARAMS(CYN_HUE, Cyan Hue, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 41 | DEFINE_UI_PARAMS(CYN_SAT, Cyan Sat, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 42 | DEFINE_UI_PARAMS(CYN_VAL, Cyan Value, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 43 | 44 | DEFINE_UI_PARAMS(MAG_HUE, Magenta Hue, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 45 | DEFINE_UI_PARAMS(MAG_SAT, Magenta Sat, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 46 | DEFINE_UI_PARAMS(MAG_VAL, Magenta Value, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 47 | 48 | DEFINE_UI_PARAMS(YEL_HUE, Yellow Hue, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 49 | DEFINE_UI_PARAMS(YEL_SAT, Yellow Sat, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 50 | DEFINE_UI_PARAMS(YEL_VAL, Yellow Value, DCTLUI_SLIDER_FLOAT, 0.0, -1.0, 1.0, 0.001) 51 | 52 | __DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) { 53 | float3 rgb; 54 | 55 | float red_r = RED_VAL + 1.0f; 56 | float red_g = RED_VAL - RED_SAT; 57 | float red_b = RED_VAL + RED_HUE - RED_SAT; 58 | 59 | float grn_r = GRN_VAL - GRN_SAT; 60 | float grn_g = GRN_VAL + 1.0f; 61 | float grn_b = GRN_VAL + GRN_HUE - GRN_SAT; 62 | 63 | float blu_r = BLU_VAL + BLU_HUE - BLU_SAT; 64 | float blu_g = BLU_VAL - BLU_SAT; 65 | float blu_b = BLU_VAL + 1.0f; 66 | 67 | float cyn_r = CYN_VAL - CYN_SAT; 68 | float cyn_g = CYN_VAL + 1.0f + CYN_HUE; 69 | float cyn_b = CYN_VAL + 1.0f; 70 | 71 | float mag_r = MAG_VAL + 1.0f; 72 | float mag_g = MAG_VAL - MAG_SAT; 73 | float mag_b = MAG_VAL + 1.0f + MAG_HUE; 74 | 75 | float yel_r = YEL_VAL + 1.0f + YEL_HUE; 76 | float yel_g = YEL_VAL + 1.0f; 77 | float yel_b = YEL_VAL - YEL_SAT; 78 | 79 | float3 blk = make_float3(BLK_RGB, BLK_RGB, BLK_RGB); 80 | float3 wht = make_float3(WHT_RGB, WHT_RGB, WHT_RGB); 81 | float3 red = make_float3(red_r, red_g, red_b); 82 | float3 grn = make_float3(grn_r, grn_g, grn_b); 83 | float3 blu = make_float3(blu_r, blu_g, blu_b); 84 | float3 cyn = make_float3(cyn_r, cyn_g, cyn_b); 85 | float3 mag = make_float3(mag_r, mag_g, mag_b); 86 | float3 yel = make_float3(yel_r, yel_g, yel_b); 87 | 88 | if (p_R > p_G) { 89 | if (p_G > p_B) { 90 | rgb = p_R * (red - blk) + blk + p_G * (yel - red) + p_B * (wht - yel); 91 | } else if (p_R > p_B) { 92 | rgb = p_R * (red - blk) + blk + p_G * (wht - mag) + p_B * (mag - red); 93 | } else { 94 | rgb = p_R * (mag - blu) + p_G * (wht - mag) + p_B * (blu - blk) + blk; 95 | } 96 | } else { 97 | if (p_B > p_G) { 98 | rgb = p_R * (wht - cyn) + p_G * (cyn - blu) + p_B * (blu - blk) + blk; 99 | } else if (p_B > p_R) { 100 | rgb = p_R * (wht - cyn) + p_G * (grn - blk) + blk + p_B * (cyn - grn); 101 | } else { 102 | rgb = p_R * (yel - grn) + p_G * (grn - blk) + blk + p_B * (wht - yel); 103 | } 104 | } 105 | 106 | return rgb; 107 | } 108 | --------------------------------------------------------------------------------