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
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

#136

Post by intelligent machine » Mon Mar 23, 2020 11:02 am

Shem Namo wrote:
Mon Mar 23, 2020 8:40 am
Thanks @intelligent machine I see it on my end to now.
What do you think could be causing it?
No idea...would have to break down all the math in a spreadsheet operation by operation using several different values for the gamma including the offending values and see what's happening in the math....could be a float error or something in the algorithm that needs a tweak but I won't have time to check into that the rest of this week....the hacky way around it would be to test for those exact values inline and just add a really really small amount if the test is true....shouldn't be an issue for most unless you keyframe an animation on that control that hits those exact values.

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

#137

Post by Shem Namo » Mon Mar 23, 2020 12:30 pm

Thanks Sam,
I honestly think it may be a float error though.
Maybe a rounding system can fix it?

Thanks again,

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

#138

Post by intelligent machine » Mon Mar 23, 2020 1:21 pm

replace "pow" with "powr" thoughtout and test. I think that should do it.

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

#139

Post by Shem Namo » Mon Mar 23, 2020 1:48 pm

Thanks @intelligent machine , I'll try that in the morning :)
in the meantime I manged to put together a trick that seems to get rid of the issue.
I'm not sure if it's a real solution though.

Please tell me what you think.

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

User avatar
Midgardsormr
Fusionator
Posts: 1756
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 14
Location: Los Angeles, CA, USA
Been thanked: 89 times
Contact:

Re: [RC] Vibrance Fuse

#140

Post by Midgardsormr » Mon Mar 23, 2020 3:37 pm

One last thing: That _fmaxf() should be only around the division problem, not around the entire power function. What you want is to prevent a divide-by-zero condition, so anywhere you have value / variable, you want to make sure the variable can never be zero. Thus:

col.x = powr(col.x, 1/_fmaxf(params->red, 0.0001f));

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

#141

Post by intelligent machine » Mon Mar 23, 2020 4:22 pm

Midgardsormr wrote:
Mon Mar 23, 2020 3:37 pm
col.x = powr(col.x, 1/_fmaxf(params->red, 0.0001f));
One tiny little alteration so you don’t end up with 100k for the power and take down the power grid.

Code: Select all


col.x = powr(col.x, _fmaxf(1/params->red, 0.0001f));


User avatar
Midgardsormr
Fusionator
Posts: 1756
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 14
Location: Los Angeles, CA, USA
Been thanked: 89 times
Contact:

Re: [RC] Vibrance Fuse

#142

Post by Midgardsormr » Mon Mar 23, 2020 4:24 pm

Does that not throw an error when red == 0?

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

#143

Post by intelligent machine » Mon Mar 23, 2020 4:37 pm

Not at a computer to verify anything but would think the result would be NaN which would be evaluated the same as zero right? I just switched it because what you had would result in 1/var or 1/0.0001 and then you would have an exponent of 10,000. (Sorry, read it as 100k before)

User avatar
Midgardsormr
Fusionator
Posts: 1756
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 14
Location: Los Angeles, CA, USA
Been thanked: 89 times
Contact:

Re: [RC] Vibrance Fuse

#144

Post by Midgardsormr » Mon Mar 23, 2020 4:52 pm

Either NaN or Inf. Either one could be troublesome.

User avatar
SecondMan
Site Admin
Posts: 4442
Joined: Thu Jul 31, 2014 5:31 pm
Answers: 26
Location: Vancouver, Canada
Been thanked: 107 times
Contact:

Re: [RC] Vibrance Fuse

#145

Post by SecondMan » Mon Mar 23, 2020 5:22 pm

intelligent machine wrote:
Mon Mar 23, 2020 4:37 pm
NaN which would be evaluated the same as zero right?
Nope nope.

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

#146

Post by intelligent machine » Mon Mar 23, 2020 6:48 pm

Well I don't mean literal zero but that it is treated the same as if it were zero in the case of fmaxf and then the other value in the argument is returned.

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

#147

Post by Shem Namo » Tue Mar 24, 2020 12:28 am

Thanks @Midgardsormr , Thanks @intelligent machine , Thanks @SecondMan!!

Sam, apparently it does some weird things when one of the color values is 0, even weirder when 2 of them equal 0 .
Can anything bad happen if gets to an exponent of 10,000? Is it dangerous?
What doe "take down the power gird" mean?

I tried Bryan's method, and it all seems to work great, I'm just worried about the whole ten thousand exponent thing.
The result of the invert looks almost identical to Video Copilot's.
I tried to de-compile their plug-in to see what algorithms they use, but it was very long and I didn't understand any of it :oops:

I saw a great video recently be Ted-Ed about dividing by zero, looks like it came in handy.

Thanks again guys,
I think as soon as we figure out this 10,000 exponent thing, it might just be ready for Reactor :D

User avatar
Midgardsormr
Fusionator
Posts: 1756
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 14
Location: Los Angeles, CA, USA
Been thanked: 89 times
Contact:

Re: [RC] Vibrance Fuse

#148

Post by Midgardsormr » Tue Mar 24, 2020 7:53 am

You'll get an insanely high value, but it'll be clipped by the maximum floating point value of 65,536, as SecondMan indicated several pages ago. But it will be an actual result instead of NaN.

I'm really not sure what you're doing there, though. What is the intent of that operation?

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

#149

Post by intelligent machine » Tue Mar 24, 2020 7:58 am

I just completely removed that section as you seem to be using it to further manipulate the invert function which should simply be:

Code: Select all

		// The Invert Control math goes here:
		if (params->invert == 1) {
			col.x = 1 - col.x;
			col.y = 1 - col.y;
			col.z = 1 - col.z;
		}
There are issues with both the Vibrance and Saturation sections that are causing NaN values to return.
Put a BC node after this fuse, turn up any one of the values and view that node when testing.

User avatar
Midgardsormr
Fusionator
Posts: 1756
Joined: Wed Nov 26, 2014 8:04 pm
Answers: 14
Location: Los Angeles, CA, USA
Been thanked: 89 times
Contact:

Re: [RC] Vibrance Fuse

#150

Post by Midgardsormr » Tue Mar 24, 2020 8:07 am

Shem Namo wrote:
Mon Mar 23, 2020 1:55 pm
col.x += + (channelm * amount);
col.y += + (channelm * amount);
col.z += + (channelm * amount);
Could be related to the extra + operator here. I have no idea what that will even do. I would have expected it to fail to compile.