Welcome to WSL!

Make yourself at home, but before posting, please may I ask you to read the following topics.


Posting 101
Server space, screenshots, and you

Thank you!

PS. please pretty please:


Image

[RC] Vibrance Fuse

Where the future is being made, today.

Welcome to the WSL development corner!

In this forum, please post your development projects. You get kudos and feedback here.
Topics ideally have preset prefixes, and this is what they (might) mean:

  • [DEV] - very much work in progress, don't build a business on this, could go anywhere
  • [BETA] - should kinda do what it's supposed to do, please test, give feedback
  • [RC] - this may end up in Reactor soon, polishing up, now's the time for last minute thoughts
  • [ABD] - died a premature death, sadness, will not see the light of day ever (unless someone picks up the scraps)

Once a development project has been released (hurray), topics can be marked as - you guessed it - [RELEASED] :cheer:

Development topics only, please. For generic questions, how-to's, questions and inquiries about existing tools etc, please go to the appropriate other forums.
User avatar
smirontsev
Posts: 7
Joined: Sat Mar 11, 2017 8:56 am
Real name: Sergey Mirontsev

Re: [RC] Vibrance Fuse

#181

Post by smirontsev » Fri Mar 27, 2020 6:41 am

Win 10
16.2.0.055 Studio
GTX 1080 Ti
... failed

User avatar
intelligent machine
Fusionista
Posts: 598
Joined: Fri May 13, 2016 10:01 pm
Answers: 6
Location: Austin, Texas, USA
Real name: Sam Treadway
Been thanked: 34 times
Contact:

Re: [RC] Vibrance Fuse

#182

Post by intelligent machine » Fri Mar 27, 2020 6:42 am

My specs:

Fu16.2, DR16.2
macOS 10.15.4
AMD Radeon Pro Vega 64, AMD Radeon VII, AMD Radeon VII

I will test on a Windows 10 Virtual Machine later.

User avatar
intelligent machine
Fusionista
Posts: 598
Joined: Fri May 13, 2016 10:01 pm
Answers: 6
Location: Austin, Texas, USA
Real name: Sam Treadway
Been thanked: 34 times
Contact:

Re: [RC] Vibrance Fuse

#183

Post by intelligent machine » Fri Mar 27, 2020 8:51 am

@Shem Namo Can you send me a version of the fuse that IS working on your platform without throwing any erros/warning?
I want to do what my diff/merge tool shows.

I installed Fu16.2 on the Windows 10 virtual machine and I get the same error that @SirEdric reported but absolutely no errors in macOS. I wasn't expecting GPU compute to work on the virtual machine anyway as the GPU isn't shared but at least this would allow me to see what errors pop up. I should also mention that I have the GPU compute API mode set to "Metal" only with device set to use all three GPUs. If I set the API mode to OpenCL and restart then of course it breaks. I have no way to test CUDA presently.

User avatar
PeterLoveday
Fusioneer
Posts: 208
Joined: Sun Sep 14, 2014 6:09 pm
Answers: 9
Been thanked: 17 times

Re: [RC] Vibrance Fuse

#184

Post by PeterLoveday » Fri Mar 27, 2020 6:31 pm

See if this is any better:
Vibrance.fuse
Note:

* I changed the abs() to fabs()
* I changed a couple of instances of 1 to 1.0f, as _fminf() needs the same type for both its arguments.
You do not have the required permissions to view the files attached to this post.

User avatar
intelligent machine
Fusionista
Posts: 598
Joined: Fri May 13, 2016 10:01 pm
Answers: 6
Location: Austin, Texas, USA
Real name: Sam Treadway
Been thanked: 34 times
Contact:

Re: [RC] Vibrance Fuse

#185

Post by intelligent machine » Fri Mar 27, 2020 7:51 pm

PeterLoveday wrote:
Fri Mar 27, 2020 6:31 pm
* I changed the abs() to fabs()
* I changed a couple of instances of 1 to 1.0f, as _fminf() needs the same type for both its arguments.
Thanks @PeterLoveday !
I had a feeling about that abs() as I was looking through it again.

Any luck getting it to run on Windows?

User avatar
PeterLoveday
Fusioneer
Posts: 208
Joined: Sun Sep 14, 2014 6:09 pm
Answers: 9
Been thanked: 17 times

Re: [RC] Vibrance Fuse

#186

Post by PeterLoveday » Fri Mar 27, 2020 9:03 pm

Haven't tried, but it works in OpenCL on Mac, so it might.

User avatar
smirontsev
Posts: 7
Joined: Sat Mar 11, 2017 8:56 am
Real name: Sergey Mirontsev

Re: [RC] Vibrance Fuse

#187

Post by smirontsev » Fri Mar 27, 2020 11:45 pm

Fu16.2 - not working in CUDA GPU API mode, working in OpenCL GPU API mode
DR16.2 - not working in CUDA GPU API mode (have not tested in OpenCL mode)

User avatar
Shem Namo
Fusionista
Posts: 502
Joined: Sun Oct 06, 2019 9:15 pm
Location: North Israel
Real name: David Kohen
Been thanked: 13 times

Re: [RC] Vibrance Fuse

#188

Post by Shem Namo » Sat Mar 28, 2020 10:12 am

Thanks @intelligent machine ,
Sorry for the late response.

The update that @PeterLoveday made fixed it, Thanks Peter.
I works perfectly on Windows now.

The invert function looks great to!!
The 4 vibrance modes all look amazing in their own way :)

Thanks for taking all of this time to improve this fuse,
I really appreciate it!!

You already took it beyond Video Copilot's plug-in.

Thanks again,

User avatar
Shem Namo
Fusionista
Posts: 502
Joined: Sun Oct 06, 2019 9:15 pm
Location: North Israel
Real name: David Kohen
Been thanked: 13 times

Re: [RC] Vibrance Fuse

#189

Post by Shem Namo » Sat Mar 28, 2020 10:30 am

I did a quick test and found that the gain operation causes some #INf pixels,
so I changed the order a little bit.

I'll keep testing :)

Thanks again,
David
Code: [Select all] [Expand/Collapse] [Download] (Tintensity.fuse)
  1. FuRegisterClass("Vibrance", CT_Tool, {
  2.     REGS_Category = "Fuses\\Color",
  3.     REGS_OpIconString = "TNT",
  4.     REGS_OpDescription = "Vibrance",
  5.     REG_Version = 1.0,
  6.     REGS_Company = "Learn Now FX",
  7.     REGS_URL = "http://www.youtube.com/LearnNowFX",
  8. })
  9.  
  10.  
  11. VibranceParams = [[
  12.     float red;
  13.     float green;
  14.     float blue;
  15.     float mode;
  16.     float vibrance;
  17.     float saturation;
  18.     float gain;
  19.     float gamma;
  20.     int unmult;
  21.     int invert;
  22.     float again;
  23.     int clip;
  24.     int srcCompOrder;
  25. ]]
  26.  
  27. VibranceKernel = [[
  28.     __KERNEL__ void VibranceKernel(__CONSTANTREF__ VibranceParams *params, __TEXTURE2D__ src, __TEXTURE2D_WRITE__ dst) {
  29.         DEFINE_KERNEL_ITERATORS_XY(x, y);
  30.         float4 col = _tex2DVecN(src, x, y, params->srcCompOrder);
  31.         float luma = col.x * 0.299f + col.y * 0.587f + col.z * 0.114f;
  32.         float vibrance = params->vibrance;
  33.        
  34.         // The Gain control math goes here:
  35.         col.x *=  params->gain;
  36.         col.y *=  params->gain;
  37.         col.z *=  params->gain;    
  38.        
  39.         // UnMultiply math:
  40.         if (params->unmult == 1) {
  41.             col.w *= (luma + params->again);
  42.         }
  43.  
  44.         // Invert Control math:
  45.         if (params->invert == 1) {
  46.             col.x = col.w * (1 - col.x);
  47.             col.y = col.w * (1 - col.y);
  48.             col.z = col.w * (1 - col.z);
  49.         }
  50.  
  51.  
  52.         // Color Picker math:
  53.         col.x += col.x * params->red;
  54.         col.y += col.y * params->green;
  55.         col.z += col.z * params->blue;
  56.  
  57.  
  58.  
  59.         // The Gamma control math goes here:
  60.         col.x = powr(col.x, 1/_fmaxf(params->gamma, 0.01f));
  61.         col.y = powr(col.y, 1/_fmaxf(params->gamma, 0.01f));
  62.         col.z = powr(col.z, 1/_fmaxf(params->gamma, 0.01f));
  63.  
  64.  
  65.         // Vibrance math:
  66.         float cMax = _fmaxf(col.x, _fmaxf(col.y, col.z));  //find the strongest color
  67.         float cMin = _fminf(col.x, _fminf(col.y, col.z));  //find the weakest color
  68.         float cSat = cMax - cMin; //The diff of min and max color is the Saturation
  69.         float cAverage = (col.x + col.y + col.z) / 3.0f;
  70.         float scale = 1.0;
  71.                 //Vibrant
  72.         if (params->mode == 0) {
  73.             scale = vibrance * (2 * (1 - cSat)); //Less Saturated given higher priority
  74.             if (cMax == col.x) { //special treatment when red is max
  75.                 scale = vibrance * (fabs(col.y - col.z) / (cSat / cAverage)) * (1 - cSat);
  76.             }
  77.                     //Clamp
  78.             scale = _fminf(1.0f, scale);
  79.                     //Lerp
  80.             col.x = (col.x - cMax) * scale + col.x;
  81.             col.y = (col.y - cMax) * scale + col.y;
  82.             col.z = (col.z - cMax) * scale + col.z;
  83.         }
  84.                 //Simple
  85.         if (params->mode == 1) {
  86.             scale = vibrance * ( 0.25 * (1 - cAverage));
  87.                     //Lerp
  88.             col.x = (col.x - cMin) * scale + col.x;
  89.             col.y = (col.y - cMin) * scale + col.y;
  90.             col.z = (col.z - cMin) * scale + col.z;
  91.         }
  92.                 //Complex
  93.         if (params->mode == 2) {
  94.             scale = vibrance * (1.0 - (sign(vibrance) * cAverage));
  95.                     //Lerp
  96.             col.x = (col.x - cAverage) * scale + col.x;
  97.             col.y = (col.y - cAverage) * scale + col.y;
  98.             col.z = (col.z - cAverage) * scale + col.z;
  99.         }
  100.                 //Power
  101.         if (params->mode == 3) {
  102.             scale = vibrance * (1.0 - powr(cSat, 1 / (vibrance + 1.0f)));
  103.                     //Clamp
  104.             scale = _fminf(1.0f, scale);
  105.                     //Lerp
  106.             col.x = (col.x - cSat) * scale + col.x;
  107.             col.y = (col.y - cSat) * scale + col.y;
  108.             col.z = (col.z - cSat) * scale + col.z;
  109.         }
  110.  
  111.  
  112.         // The Saturation math goes here:
  113.         col.x = params->saturation * col.x + (1-params->saturation) * luma;
  114.         col.y = params->saturation * col.y + (1-params->saturation) * luma;
  115.         col.z = params->saturation * col.z + (1-params->saturation) * luma;
  116.  
  117.  
  118.         //the Clip negative Pixels math goes here:
  119.         if (params->clip == 1) {
  120.             if (col.x < 0) { col.x = 0; }
  121.             if (col.y < 0) { col.y = 0; }
  122.             if (col.z < 0) { col.z = 0; }
  123.         }
  124.  
  125.  
  126.         _tex2DVec4Write(dst, x, y, col);
  127.     }
  128. ]]
  129.  
  130. OpenDemoURL = [[
  131. -- Open a webpage window up using your default web browser
  132.     platform = (FuPLATFORM_WINDOWS and "Windows") or (FuPLATFORM_MAC and "Mac") or (FuPLATFORM_LINUX and "Linux")
  133.     function OpenURL(siteName, path)
  134.         if platform == "Windows" then
  135.             -- Running on Windows
  136.             command = "explorer \"" .. path .. "\""
  137.         elseif platform == "Mac" then
  138.             -- Running on Mac
  139.             command = "open \"" .. path .. "\" &"
  140.         elseif platform == "Linux" then
  141.             -- Running on Linux
  142.             command = "xdg-open \"" .. path .. "\" &"
  143.         else
  144.             print("[Error] There is an invalid Fusion platform detected")
  145.             return
  146.         end
  147.  
  148.         os.execute(command)
  149.         -- print("[Launch Command] ", command)
  150.         print("[Opening URL] [" .. siteName .. "] " .. path)
  151.     end
  152.  
  153.     OpenURL("Demo", "https://youtu.be/2XF8BsJ1J5o")
  154. ]]
  155.  
  156. function Create()
  157.     self:BeginControlNest("Tint", "Tint", true, {})
  158.         InShowWheel = self:AddInput("Show Advanced", "ShowAdvanced", {
  159.             LINKID_DataType = "Number",
  160.             INPID_InputControl = "CheckboxControl",
  161.             INP_Integer = true,
  162.             ICD_Width = 0.5,
  163.             INP_Default = 0,
  164.             INP_External = false,
  165.             INP_DoNotifyChanged = true,
  166.         })
  167.         InColorR = self:AddInput("Red", "Red", {
  168.             ICS_Name            = "Color",
  169.             LINKID_DataType     = "Number",
  170.             INPID_InputControl  = "ColorControl",
  171.             INP_Default         = 0,
  172.             INP_MaxScale        = 1.0,
  173.             ICD_Center          = 1.0,
  174.             INP_DoNotifyChanged = true,
  175.             CLRC_ShowWheel      = false,
  176.             IC_ControlGroup     = 1,
  177.             IC_ControlID        = 0,
  178.             IC_Visible          = true,
  179.         })
  180.         InColorG = self:AddInput("Green", "Green", {
  181.             LINKID_DataType     = "Number",
  182.             INPID_InputControl  = "ColorControl",
  183.             INP_Default         = 0,
  184.             INP_DoNotifyChanged = true,
  185.             IC_ControlGroup     = 1,
  186.             IC_ControlID        = 1,
  187.         })
  188.         InColorB = self:AddInput("Blue", "Blue", {
  189.             LINKID_DataType     = "Number",
  190.             INPID_InputControl  = "ColorControl",
  191.             INP_Default         = 0,
  192.             INP_DoNotifyChanged = true,
  193.             IC_ControlGroup     = 1,
  194.             IC_ControlID        = 2,
  195.         })
  196.         InInvert = self:AddInput("Invert", "Invert", {
  197.             LINKID_DataType = "Number",
  198.             INPID_InputControl = "CheckboxControl",
  199.             INP_Integer = true,
  200.             ICD_Width = 0.5,
  201.             INP_Default = 0,
  202.         })
  203.     self:EndControlNest()
  204.  
  205.     self:BeginControlNest("Intensity", "Intensity", true, {})
  206.         InVibranceMode = self:AddInput("Vibrance Mode", "VibranceMode", {
  207.             LINKID_DataType = "Number",
  208.             INPID_InputControl = "ComboControl",
  209.             INP_MinScale = 0,
  210.             INP_MaxAllowed = 3,
  211.             INP_MinAllowed = 0,
  212.             INP_MaxAllowed = 3,
  213.             INP_Integer = true,
  214.             ICD_Width = 1.0,
  215.             CC_LabelPosition = "Horizontal",
  216.             INP_DoNotifyChanged = true,
  217.             { CCS_AddString = "Vibrant", },
  218.             { CCS_AddString = "Simple", },
  219.             { CCS_AddString = "Complex", },
  220.             { CCS_AddString = "Power", },
  221.         })
  222.         InVibrance = self:AddInput("Vibrance", "Vibrance", {
  223.             LINKID_DataType = "Number",
  224.             INPID_InputControl = "SliderControl",
  225.             INP_Default = 0,
  226.             INP_MinScale = 0,
  227.             INP_MaxScale = 3,
  228.             INP_Default = 1,
  229.         })
  230.         InSaturation = self:AddInput("Saturation", "Saturation", {
  231.             LINKID_DataType = "Number",
  232.             INPID_InputControl = "SliderControl",
  233.             INP_MinScale = 0,
  234.             INP_MaxScale = 2,
  235.             INP_Default = 1,
  236.         })
  237.         InGain = self:AddInput("Gain", "Gain", {
  238.             LINKID_DataType = "Number",
  239.             INPID_InputControl = "SliderControl",
  240.             INP_MinScale = 0,
  241.             INP_MaxScale = 5,
  242.             INP_Default = 1,
  243.         })
  244.         InGamma = self:AddInput("Gamma", "Gamma", {
  245.             LINKID_DataType = "Number",
  246.             INPID_InputControl = "SliderControl",
  247.             INP_MinScale = 0,
  248.             INP_MaxScale = 2,
  249.             INP_Default = 1,
  250.         })
  251.     self:EndControlNest()
  252.  
  253.     self:BeginControlNest("Alpha", "Alpha", true, {})
  254.         InUnMultiply = self:AddInput("UnMultiply", "UnMultiply", {
  255.             LINKID_DataType = "Number",
  256.             INPID_InputControl = "CheckboxControl",
  257.             INP_Integer = true,
  258.             INP_Default = 0,
  259.         })
  260.         InAlphaGain = self:AddInput("Alpha Gain", "Alpha Gain", {
  261.             LINKID_DataType = "Number",
  262.             INPID_InputControl = "SliderControl",
  263.             INP_MinScale = 0,
  264.             INP_MaxScale = 1,
  265.             INP_Default = 0,
  266.         })
  267.     self:EndControlNest()
  268.  
  269.     self:BeginControlNest("Advanced", "Advanced", false, {})
  270.         InDepth = self:AddInput("Depth", "Depth", {
  271.             LINKID_DataType = "Number",
  272.             INPID_InputControl = "ComboControl",
  273.             INP_Default = 2.0,
  274.             INP_Integer = true,
  275.             ICD_Width = 1.0,
  276.             CC_LabelPosition = "Vertical",
  277.             INP_DoNotifyChanged = true,
  278.             { CCS_AddString = "int8", },
  279.             { CCS_AddString = "int16", },
  280.             { CCS_AddString = "float 16", },
  281.             { CCS_AddString = "float 32", },
  282.             INP_External = false,
  283.         })
  284.         InClip = self:AddInput("Clip Negative Pixels", "Clip Negative Pixels", {
  285.             LINKID_DataType = "Number",
  286.             INPID_InputControl = "CheckboxControl",
  287.             INP_Integer = true,
  288.             ICD_Width = 1.0,
  289.             INP_Default = 1,
  290.             INP_External = false,
  291.         })
  292.         DemoButton = self:AddInput("Demo", "Demo", {
  293.             LINKS_Name = "Demo",
  294.             LINKID_DataType = "Number",
  295.             INPID_InputControl = "ButtonControl",
  296.             BTNCS_Execute = OpenDemoURL,
  297.         })
  298.     self:EndControlNest()
  299.  
  300.     InImage = self:AddInput("Image", "Image", {
  301.         LINKID_DataType = "Image",
  302.         LINK_Main = 1,
  303.         INP_AcceptsGPUImages = true,
  304.     })
  305.     OutImage = self:AddOutput("Output", "Output", {
  306.         LINKID_DataType = "Image",
  307.         LINK_Main = 1,
  308.     })
  309. end
  310.  
  311.  
  312. function NotifyChanged(inp, param, time)
  313.     if inp ~= nil and param ~= nil then
  314.         if inp == InShowWheel then
  315.             if param.Value == 1.0 then
  316.                 InColorR:SetAttrs({ CLRC_ShowWheel = true, })
  317.             else
  318.                 InColorR:SetAttrs({ CLRC_ShowWheel = false, })
  319.             end
  320.         end
  321.     end
  322. end
  323.  
  324.  
  325. function Process(req)
  326.     local src = InImage:GetValue(req)
  327.     local depth = InDepth:GetValue(req).Value
  328.     local dst = Image{ IMG_Like = src, IMG_Depth = depth + 1, IMG_DeferAlloc = true }
  329.  
  330.     local node = DVIPComputeNode(req, "VibranceKernel", VibranceKernel, "VibranceParams", VibranceParams)
  331.     local params = node:GetParamBlock(VibranceParams)
  332.  
  333.     params.red = InColorR:GetValue(req).Value
  334.     params.green = InColorG:GetValue(req).Value
  335.     params.blue = InColorB:GetValue(req).Value
  336.     params.mode = InVibranceMode:GetValue(req).Value
  337.     params.vibrance = InVibrance:GetValue(req).Value
  338.     params.saturation = InSaturation:GetValue(req).Value
  339.     params.gain = InGain:GetValue(req).Value
  340.     params.gamma = InGamma:GetValue(req).Value
  341.     params.unmult = InUnMultiply:GetValue(req).Value
  342.     params.again = InAlphaGain:GetValue(req).Value
  343.     params.invert = InInvert:GetValue(req).Value
  344.     params.clip = InClip:GetValue(req).Value
  345.     params.srcCompOrder = src:IsMask() and 1 or 15
  346.  
  347.     node:SetParamBlock(params)
  348.  
  349.     node:AddInput("src", src)
  350.     node:AddOutput("dst", dst)
  351.  
  352.     local ok = node:RunSession(req)
  353.  
  354.     if not ok then
  355.         dst = nil
  356.     end
  357.  
  358.     OutImage:Set(req, dst)
  359. end

User avatar
intelligent machine
Fusionista
Posts: 598
Joined: Fri May 13, 2016 10:01 pm
Answers: 6
Location: Austin, Texas, USA
Real name: Sam Treadway
Been thanked: 34 times
Contact:

Re: [RC] Vibrance Fuse

#190

Post by intelligent machine » Sat Mar 28, 2020 11:34 am

Shem Namo wrote:
Sat Mar 28, 2020 10:30 am
I did a quick test and found that the gain operation causes some #INf pixels,
so I changed the order a little bit
I didn’t really touch the gain and gamma controls much. I guess a decision needs to be made on what version of the image these adjustments should be made on. If before colorization and vibrance, then they should be removed and just use a regular BC as needed before reaching this tool. So I think they should actually go after the colorization and vibrance are applied and saturation after gain.

Some work still needs to be done for the process function as well. Right now something funky is happening on returning the image for output. Open the histogram and you will only have access to 1 channel.

User avatar
Shem Namo
Fusionista
Posts: 502
Joined: Sun Oct 06, 2019 9:15 pm
Location: North Israel
Real name: David Kohen
Been thanked: 13 times

Re: [RC] Vibrance Fuse

#191

Post by Shem Namo » Sun Mar 29, 2020 8:46 am

I tried playing with some of the operations and I think this version is pretty stable.
I tried all of the controls animated and everything seems fine.

I tried changing the places of the * and +, in tint operation and the results looks pretty good
and the color values aren't so high.

Is there any disadvantage to this?

Thanks again,
David.
Code: [Select all] [Expand/Collapse] [Download] (Tintensity.fuse)
  1. FuRegisterClass("Vibrance", CT_Tool, {
  2.     REGS_Category = "Fuses\\Color",
  3.     REGS_OpIconString = "TNT",
  4.     REGS_OpDescription = "Vibrance",
  5.     REG_Version = 1.0,
  6.     REGS_Company = "Learn Now FX",
  7.     REGS_URL = "http://www.youtube.com/LearnNowFX",
  8. })
  9.  
  10.  
  11. VibranceParams = [[
  12.     float red;
  13.     float green;
  14.     float blue;
  15.     float mode;
  16.     float vibrance;
  17.     float saturation;
  18.     float gain;
  19.     float gamma;
  20.     int unmult;
  21.     int invert;
  22.     float again;
  23.     int clip;
  24.     int srcCompOrder;
  25. ]]
  26.  
  27. VibranceKernel = [[
  28.     __KERNEL__ void VibranceKernel(__CONSTANTREF__ VibranceParams *params, __TEXTURE2D__ src, __TEXTURE2D_WRITE__ dst) {
  29.         DEFINE_KERNEL_ITERATORS_XY(x, y);
  30.         float4 col = _tex2DVecN(src, x, y, params->srcCompOrder);
  31.         float luma = col.x * 0.299f + col.y * 0.587f + col.z * 0.114f;
  32.         float vibrance = params->vibrance;
  33.        
  34.         // The Gain control math goes here:
  35.         col.x *=  params->gain;
  36.         col.y *=  params->gain;
  37.         col.z *=  params->gain;    
  38.        
  39.         // UnMultiply math:
  40.         if (params->unmult == 1) {
  41.             col.w *= (luma + params->again);
  42.         }
  43.  
  44.         // Invert Control math:
  45.         if (params->invert == 1) {
  46.             col.x = col.w * (1 - col.x);
  47.             col.y = col.w * (1 - col.y);
  48.             col.z = col.w * (1 - col.z);
  49.         }
  50.  
  51.  
  52.         // Color Picker math:
  53.         col.x *= col.x + params->red;
  54.         col.y *= col.y + params->green;
  55.         col.z *= col.z + params->blue;
  56.  
  57.  
  58.  
  59.         // The Gamma control math goes here:
  60.         col.x = powr(col.x, 1/_fmaxf(params->gamma, 0.01f));
  61.         col.y = powr(col.y, 1/_fmaxf(params->gamma, 0.01f));
  62.         col.z = powr(col.z, 1/_fmaxf(params->gamma, 0.01f));
  63.  
  64.  
  65.         // Vibrance math:
  66.         float cMax = _fmaxf(col.x, _fmaxf(col.y, col.z));  //find the strongest color
  67.         float cMin = _fminf(col.x, _fminf(col.y, col.z));  //find the weakest color
  68.         float cSat = cMax - cMin; //The diff of min and max color is the Saturation
  69.         float cAverage = (col.x + col.y + col.z) / 3.0f;
  70.         float scale = 1.0;
  71.                 //Vibrant
  72.         if (params->mode == 0) {
  73.             scale = vibrance * (2 * (1 - cSat)); //Less Saturated given higher priority
  74.             if (cMax == col.x) { //special treatment when red is max
  75.                 scale = vibrance * (fabs(col.y - col.z) / (cSat / cAverage)) * (1 - cSat);
  76.             }
  77.                     //Clamp
  78.             scale = _fminf(1.0f, scale);
  79.                     //Lerp
  80.             col.x = (col.x - cMax) * scale + col.x;
  81.             col.y = (col.y - cMax) * scale + col.y;
  82.             col.z = (col.z - cMax) * scale + col.z;
  83.         }
  84.                 //Simple
  85.         if (params->mode == 1) {
  86.             scale = vibrance * ( 0.25 * (1 - cAverage));
  87.                     //Lerp
  88.             col.x = (col.x - cMin) * scale + col.x;
  89.             col.y = (col.y - cMin) * scale + col.y;
  90.             col.z = (col.z - cMin) * scale + col.z;
  91.         }
  92.                 //Complex
  93.         if (params->mode == 2) {
  94.             scale = vibrance * (1.0 - (sign(vibrance) * cAverage));
  95.                     //Lerp
  96.             col.x = (col.x - cAverage) * scale + col.x;
  97.             col.y = (col.y - cAverage) * scale + col.y;
  98.             col.z = (col.z - cAverage) * scale + col.z;
  99.         }
  100.                 //Power
  101.         if (params->mode == 3) {
  102.             scale = vibrance * (1.0 - powr(cSat, 1 / (vibrance + 1.0f)));
  103.                     //Clamp
  104.             scale = _fminf(1.0f, scale);
  105.                     //Lerp
  106.             col.x = (col.x - cSat) * scale + col.x;
  107.             col.y = (col.y - cSat) * scale + col.y;
  108.             col.z = (col.z - cSat) * scale + col.z;
  109.         }
  110.  
  111.  
  112.         // The Saturation math goes here:
  113.         col.x = params->saturation * col.x + (1-params->saturation) * luma;
  114.         col.y = params->saturation * col.y + (1-params->saturation) * luma;
  115.         col.z = params->saturation * col.z + (1-params->saturation) * luma;
  116.  
  117.  
  118.         //the Clip negative Pixels math goes here:
  119.         if (params->clip == 1) {
  120.             if (col.x < 0) { col.x = 0; }
  121.             if (col.y < 0) { col.y = 0; }
  122.             if (col.z < 0) { col.z = 0; }
  123.         }
  124.  
  125.  
  126.         _tex2DVec4Write(dst, x, y, col);
  127.     }
  128. ]]
  129.  
  130. OpenDemoURL = [[
  131. -- Open a webpage window up using your default web browser
  132.     platform = (FuPLATFORM_WINDOWS and "Windows") or (FuPLATFORM_MAC and "Mac") or (FuPLATFORM_LINUX and "Linux")
  133.     function OpenURL(siteName, path)
  134.         if platform == "Windows" then
  135.             -- Running on Windows
  136.             command = "explorer \"" .. path .. "\""
  137.         elseif platform == "Mac" then
  138.             -- Running on Mac
  139.             command = "open \"" .. path .. "\" &"
  140.         elseif platform == "Linux" then
  141.             -- Running on Linux
  142.             command = "xdg-open \"" .. path .. "\" &"
  143.         else
  144.             print("[Error] There is an invalid Fusion platform detected")
  145.             return
  146.         end
  147.  
  148.         os.execute(command)
  149.         -- print("[Launch Command] ", command)
  150.         print("[Opening URL] [" .. siteName .. "] " .. path)
  151.     end
  152.  
  153.     OpenURL("Demo", "https://youtu.be/2XF8BsJ1J5o")
  154. ]]
  155.  
  156. function Create()
  157.     self:BeginControlNest("Tint", "Tint", true, {})
  158.         InShowWheel = self:AddInput("Show Advanced", "ShowAdvanced", {
  159.             LINKID_DataType = "Number",
  160.             INPID_InputControl = "CheckboxControl",
  161.             INP_Integer = true,
  162.             ICD_Width = 1.0,
  163.             INP_Default = 0,
  164.             INP_External = false,
  165.             INP_DoNotifyChanged = true,
  166.         })
  167.         InColorR = self:AddInput("Red", "Red", {
  168.             ICS_Name            = "Color",
  169.             LINKID_DataType     = "Number",
  170.             INPID_InputControl  = "ColorControl",
  171.             INP_Default         = 1,
  172.             INP_MaxScale        = 1.0,
  173.             ICD_Center          = 1.0,
  174.             INP_DoNotifyChanged = true,
  175.             CLRC_ShowWheel      = false,
  176.             IC_ControlGroup     = 1,
  177.             IC_ControlID        = 0,
  178.             IC_Visible          = true,
  179.         })
  180.         InColorG = self:AddInput("Green", "Green", {
  181.             LINKID_DataType     = "Number",
  182.             INPID_InputControl  = "ColorControl",
  183.             INP_Default         = 1,
  184.             INP_DoNotifyChanged = true,
  185.             IC_ControlGroup     = 1,
  186.             IC_ControlID        = 1,
  187.         })
  188.         InColorB = self:AddInput("Blue", "Blue", {
  189.             LINKID_DataType     = "Number",
  190.             INPID_InputControl  = "ColorControl",
  191.             INP_Default         = 1,
  192.             INP_DoNotifyChanged = true,
  193.             IC_ControlGroup     = 1,
  194.             IC_ControlID        = 2,
  195.         })
  196.         InInvert = self:AddInput("Invert", "Invert", {
  197.             LINKID_DataType = "Number",
  198.             INPID_InputControl = "CheckboxControl",
  199.             INP_Integer = true,
  200.             ICD_Width = 0.5,
  201.             INP_Default = 0,
  202.         })
  203.     self:EndControlNest()
  204.  
  205.     self:BeginControlNest("Intensity", "Intensity", true, {})
  206.         InVibranceMode = self:AddInput("Vibrance Mode", "VibranceMode", {
  207.             LINKID_DataType = "Number",
  208.             INPID_InputControl = "ComboControl",
  209.             INP_MinScale = 0,
  210.             INP_MaxAllowed = 3,
  211.             INP_MinAllowed = 0,
  212.             INP_MaxAllowed = 3,
  213.             INP_Integer = true,
  214.             ICD_Width = 1.0,
  215.             CC_LabelPosition = "Horizontal",
  216.             INP_DoNotifyChanged = true,
  217.             { CCS_AddString = "Vibrant", },
  218.             { CCS_AddString = "Simple", },
  219.             { CCS_AddString = "Complex", },
  220.             { CCS_AddString = "Power", },
  221.         })
  222.         InVibrance = self:AddInput("Vibrance", "Vibrance", {
  223.             LINKID_DataType = "Number",
  224.             INPID_InputControl = "SliderControl",
  225.             INP_Default = 0,
  226.             INP_MinScale = 0,
  227.             INP_MaxScale = 3,
  228.             INP_Default = 1,
  229.         })
  230.         InSaturation = self:AddInput("Saturation", "Saturation", {
  231.             LINKID_DataType = "Number",
  232.             INPID_InputControl = "SliderControl",
  233.             INP_MinScale = 0,
  234.             INP_MaxScale = 2,
  235.             INP_Default = 1,
  236.         })
  237.         InGain = self:AddInput("Gain", "Gain", {
  238.             LINKID_DataType = "Number",
  239.             INPID_InputControl = "SliderControl",
  240.             INP_MinScale = 0,
  241.             INP_MaxScale = 5,
  242.             INP_Default = 1,
  243.         })
  244.         InGamma = self:AddInput("Gamma", "Gamma", {
  245.             LINKID_DataType = "Number",
  246.             INPID_InputControl = "SliderControl",
  247.             INP_MinScale = 0,
  248.             INP_MaxScale = 2,
  249.             INP_Default = 1,
  250.         })
  251.     self:EndControlNest()
  252.  
  253.     self:BeginControlNest("Alpha", "Alpha", true, {})
  254.         InUnMultiply = self:AddInput("UnMultiply", "UnMultiply", {
  255.             LINKID_DataType = "Number",
  256.             INPID_InputControl = "CheckboxControl",
  257.             INP_Integer = true,
  258.             INP_Default = 0,
  259.         })
  260.         InAlphaGain = self:AddInput("Alpha Gain", "Alpha Gain", {
  261.             LINKID_DataType = "Number",
  262.             INPID_InputControl = "SliderControl",
  263.             INP_MinScale = 0,
  264.             INP_MaxScale = 1,
  265.             INP_Default = 0,
  266.         })
  267.     self:EndControlNest()
  268.  
  269.     self:BeginControlNest("Advanced", "Advanced", false, {})
  270.         InDepth = self:AddInput("Depth", "Depth", {
  271.             LINKID_DataType = "Number",
  272.             INPID_InputControl = "ComboControl",
  273.             INP_Default = 2.0,
  274.             INP_Integer = true,
  275.             ICD_Width = 1.0,
  276.             CC_LabelPosition = "Vertical",
  277.             INP_DoNotifyChanged = true,
  278.             { CCS_AddString = "int8", },
  279.             { CCS_AddString = "int16", },
  280.             { CCS_AddString = "float 16", },
  281.             { CCS_AddString = "float 32", },
  282.             INP_External = false,
  283.         })
  284.         InClip = self:AddInput("Clip Negative Pixels", "Clip Negative Pixels", {
  285.             LINKID_DataType = "Number",
  286.             INPID_InputControl = "CheckboxControl",
  287.             INP_Integer = true,
  288.             ICD_Width = 1.0,
  289.             INP_Default = 1,
  290.             INP_External = false,
  291.         })
  292.         DemoButton = self:AddInput("Demo", "Demo", {
  293.             LINKS_Name = "Demo",
  294.             LINKID_DataType = "Number",
  295.             INPID_InputControl = "ButtonControl",
  296.             BTNCS_Execute = OpenDemoURL,
  297.         })
  298.     self:EndControlNest()
  299.  
  300.     InImage = self:AddInput("Image", "Image", {
  301.         LINKID_DataType = "Image",
  302.         LINK_Main = 1,
  303.         INP_AcceptsGPUImages = true,
  304.     })
  305.     OutImage = self:AddOutput("Output", "Output", {
  306.         LINKID_DataType = "Image",
  307.         LINK_Main = 1,
  308.     })
  309. end
  310.  
  311.  
  312. function NotifyChanged(inp, param, time)
  313.     if inp ~= nil and param ~= nil then
  314.         if inp == InShowWheel then
  315.             if param.Value == 1.0 then
  316.                 InColorR:SetAttrs({ CLRC_ShowWheel = true, })
  317.             else
  318.                 InColorR:SetAttrs({ CLRC_ShowWheel = false, })
  319.             end
  320.         end
  321.     end
  322. end
  323.  
  324.  
  325. function Process(req)
  326.     local src = InImage:GetValue(req)
  327.     local depth = InDepth:GetValue(req).Value
  328.     local dst = Image{ IMG_Like = src, IMG_Depth = depth + 1, IMG_DeferAlloc = true }
  329.  
  330.     local node = DVIPComputeNode(req, "VibranceKernel", VibranceKernel, "VibranceParams", VibranceParams)
  331.     local params = node:GetParamBlock(VibranceParams)
  332.  
  333.     params.red = InColorR:GetValue(req).Value
  334.     params.green = InColorG:GetValue(req).Value
  335.     params.blue = InColorB:GetValue(req).Value
  336.     params.mode = InVibranceMode:GetValue(req).Value
  337.     params.vibrance = InVibrance:GetValue(req).Value
  338.     params.saturation = InSaturation:GetValue(req).Value
  339.     params.gain = InGain:GetValue(req).Value
  340.     params.gamma = InGamma:GetValue(req).Value
  341.     params.unmult = InUnMultiply:GetValue(req).Value
  342.     params.again = InAlphaGain:GetValue(req).Value
  343.     params.invert = InInvert:GetValue(req).Value
  344.     params.clip = InClip:GetValue(req).Value
  345.     params.srcCompOrder = src:IsMask() and 1 or 15
  346.  
  347.     node:SetParamBlock(params)
  348.  
  349.     node:AddInput("src", src)
  350.     node:AddOutput("dst", dst)
  351.  
  352.     local ok = node:RunSession(req)
  353.  
  354.     if not ok then
  355.         dst = nil
  356.     end
  357.  
  358.     OutImage:Set(req, dst)
  359. end

User avatar
smirontsev
Posts: 7
Joined: Sat Mar 11, 2017 8:56 am
Real name: Sergey Mirontsev

Re: [RC] Vibrance Fuse

#192

Post by smirontsev » Sun Mar 29, 2020 9:23 am

Should it work on CUDA?

User avatar
Shem Namo
Fusionista
Posts: 502
Joined: Sun Oct 06, 2019 9:15 pm
Location: North Israel
Real name: David Kohen
Been thanked: 13 times

Re: [RC] Vibrance Fuse

#193

Post by Shem Namo » Sun Mar 29, 2020 9:28 am

@smirontsev, I'm pretty sure that DCTL works on Metal Cuda and OpenCL.

Thanks,
David.

User avatar
thibaud
Fusioneer
Posts: 193
Joined: Thu Sep 04, 2014 1:23 am
Been thanked: 6 times
Contact:

Re: [RC] Vibrance Fuse

#194

Post by thibaud » Sun Mar 29, 2020 12:49 pm

Windows 10 Geforce RTX 2070 latest drivers (445.75)
Fusion Studio 16.1 Gpu set to auto: RT kernel VibranceKernel failed to build
Fusion Studio 16.1 Gpu set to OpenCL: Warning: exception during GPU buffer download as soon as you touch any controls under vibrance
Same thing in Fusion Studio 16.2

User avatar
Shem Namo
Fusionista
Posts: 502
Joined: Sun Oct 06, 2019 9:15 pm
Location: North Israel
Real name: David Kohen
Been thanked: 13 times

Re: [RC] Vibrance Fuse

#195

Post by Shem Namo » Sun Mar 29, 2020 1:01 pm

@thibaud , Does the fuse return an image or does it just fail?

Thanks