VEX/VOP - Overlay /other blending modes?
2485 5 0- Ya_rp
- Member
- 4 posts
- Joined: April 2016
- Offline
Hey,
is there a way to change @Cd by another attribute(ramp),
but in a way that Overlay blending mode does?
Let say i have @Cd and f@mask (0 to 1 range) or v@colorgradient attribute
and i want to affect @Cd using @mask/@colorgradaient like overlay blending mode does.
Is there a relatively simple way to do this or i have to do some more complicated math?
is there a way to change @Cd by another attribute(ramp),
but in a way that Overlay blending mode does?
Let say i have @Cd and f@mask (0 to 1 range) or v@colorgradient attribute
and i want to affect @Cd using @mask/@colorgradaient like overlay blending mode does.
Is there a relatively simple way to do this or i have to do some more complicated math?
Edited by Ya_rp - Aug. 26, 2021 07:37:36
Houdini Indie / Redshift
instagram.com/jakubrupa
instagram.com/jakubrupa
- animatrix_
- Member
- 4523 posts
- Joined: Feb. 2012
- Offline
Hi,
You can use Color Mix VOP for some basic blending operations:
https://www.sidefx.com/docs/houdini/nodes/vop/colormix.html [www.sidefx.com]
For an exhaustive Photoshop style blending, you need to implement your own:
https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdf_reference_archive/blend_modes.pdf [www.adobe.com]
You can use Color Mix VOP for some basic blending operations:
https://www.sidefx.com/docs/houdini/nodes/vop/colormix.html [www.sidefx.com]
For an exhaustive Photoshop style blending, you need to implement your own:
https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdf_reference_archive/blend_modes.pdf [www.adobe.com]
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]
youtube.com/@pragmaticvfx | patreon.com/animatrix | pragmaticvfx.gumroad.com
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]
youtube.com/@pragmaticvfx | patreon.com/animatrix | pragmaticvfx.gumroad.com
- Ya_rp
- Member
- 4 posts
- Joined: April 2016
- Offline
Thank you animatrix,
this is what i wanted to know.
Colormix works, but gives me washed out colors.
So there is no easy premade solution.
Implementing my own is to much for me, for now.
But now i have an idea how to do this on the Redshift side.
Thanks again animatrix
this is what i wanted to know.
Colormix works, but gives me washed out colors.
So there is no easy premade solution.
Implementing my own is to much for me, for now.
But now i have an idea how to do this on the Redshift side.
Thanks again animatrix
Houdini Indie / Redshift
instagram.com/jakubrupa
instagram.com/jakubrupa
- animatrix_
- Member
- 4523 posts
- Joined: Feb. 2012
- Offline
If you want to blend colors intuitively I would recommend using the LCh color space:
https://en.wikipedia.org/wiki/HCL_color_space [en.wikipedia.org]
LCh is a perceptually uniform reference color space based on actual studies of how people perceive colors, which is just a polar transform of LAB.
https://www.wolfram.com/mathematica/new-in-10/enhanced-color-support-and-processing/cie-lchab-rendered-in-lab-space.html [www.wolfram.com]
I implemented this years ago as a VOP:
https://www.dropbox.com/s/ty9vsuz3oqrza15/BlendColor_VOP_Animatrix.otl?dl=1 [www.dropbox.com]
By default this operator blends colors using the LCh color space.
To implement the LCh color space, you first need to implement the Lab color space. Note that the Lab color space provided by this operator is different than the one in Houdini. If you use the Lab color space available in Houdini by default to implement the LCh color space, you won't get correct results. At least in my extensive tests.
RFE pending.
Here is the code for completeness:
https://en.wikipedia.org/wiki/HCL_color_space [en.wikipedia.org]
LCh is a perceptually uniform reference color space based on actual studies of how people perceive colors, which is just a polar transform of LAB.
https://www.wolfram.com/mathematica/new-in-10/enhanced-color-support-and-processing/cie-lchab-rendered-in-lab-space.html [www.wolfram.com]
I implemented this years ago as a VOP:
https://www.dropbox.com/s/ty9vsuz3oqrza15/BlendColor_VOP_Animatrix.otl?dl=1 [www.dropbox.com]
By default this operator blends colors using the LCh color space.
To implement the LCh color space, you first need to implement the Lab color space. Note that the Lab color space provided by this operator is different than the one in Houdini. If you use the Lab color space available in Houdini by default to implement the LCh color space, you won't get correct results. At least in my extensive tests.
RFE pending.
Here is the code for completeness:
{ // Original color conversion methods from ColorMine library // http://github.com/THEjoezack/ColorMine // Conversion methods to LAB color space float pivotxyz ( float n ) { float epsilon = 0.008856; float kappa = 903.3; return n > epsilon ? cbrt ( n ) : ( kappa * n + 16 ) / 116; } vector xyz2lab ( vector xyz ) { vector white = { 95.047, 100.000, 108.883 }; float x = pivotxyz ( xyz.x / white.x ); float y = pivotxyz ( xyz.y / white.y ); float z = pivotxyz ( xyz.z / white.z ); float l = max ( 0, 116 * y - 16 ); float a = 500 * ( x - y ); float b = 200 * ( y - z ); return set ( l, a, b ); } vector lch2lab ( vector lch ) { float h = radians ( lch.z ); float l = lch.x; float a = cos ( h ) * lch.y; float b = sin ( h ) * lch.y; return set ( l, a, b ); } // Conversion methods to XYZ color space vector lab2xyz ( vector lab ) { float epsilon = 0.008856; float kappa = 903.3; vector white = { 95.047, 100.000, 108.883 }; float y = ( lab.x + 16.0 ) / 116.0; float x = lab.y / 500.0 + y; float z = y - lab.z / 200.0; float x3 = x * x * x; float z3 = z * z * z; x = white.x * ( x3 > epsilon ? x3 : ( x - 16.0 / 116.0 ) / 7.787 ); y = white.y * ( lab.x > ( kappa * epsilon ) ? pow ( ( ( lab.x + 16.0 ) / 116.0 ), 3 ) : lab.x / kappa ); z = white.z * ( z3 > epsilon ? z3 : ( z - 16.0 / 116.0 ) / 7.787 ); return set ( x, y, z ); } vector lch2xyz ( vector lch ) { return lab2xyz ( lch2lab ( lch ) ); } float pivotrgb ( float n ) { return ( n > 0.04045 ? pow ( ( n + 0.055 ) / 1.055, 2.4 ) : n / 12.92 ) * 100.0; } vector rgb2xyz ( vector rgb ) { float r = pivotrgb ( rgb.x / 255.0 ); float g = pivotrgb ( rgb.y / 255.0 ); float b = pivotrgb ( rgb.z / 255.0 ); // Observer = 2°, Illuminant = D65 float x = r * 0.4124 + g * 0.3576 + b * 0.1805; float y = r * 0.2126 + g * 0.7152 + b * 0.0722; float z = r * 0.0193 + g * 0.1192 + b * 0.9505; return set ( x, y, z ); } // Conversion methods to LAB color space [Separated due to VEX compiler limitations] vector rgb2lab ( vector rgb ) { return xyz2lab ( rgb2xyz ( rgb ) ); } // Conversion methods to LCH color space vector lab2lch ( vector lab ) { float h = atan2 ( lab.z, lab.y ); h = degrees ( h ); if ( h < 0 ) h += 360.0; else if ( h >= 360 ) h -= 360.0; float l = lab.x; float c = sqrt ( lab.y * lab.y + lab.z * lab.z ); return set ( l, c, h ); } vector xyz2lch ( vector xyz ) { return lab2lch ( xyz2lab ( xyz ) ); } vector rgb2lch ( vector rgb ) { return lab2lch ( rgb2lab ( rgb ) ); } // Conversion methods to RGB color space vector xyz2rgb ( vector xyz ) { // Observer = 2°, Illuminant = D65 float x = xyz.x / 100.0; float y = xyz.y / 100.0; float z = xyz.z / 100.0; float r = x * 3.2406 + y * -1.5372 + z * -0.4986; float g = x * -0.9689 + y * 1.8758 + z * 0.0415; float b = x * 0.0557 + y * -0.2040 + z * 1.0570; r = r > 0.0031308 ? 1.055 * pow ( r, 1 / 2.4 ) - 0.055 : 12.92 * r; g = g > 0.0031308 ? 1.055 * pow ( g, 1 / 2.4 ) - 0.055 : 12.92 * g; b = b > 0.0031308 ? 1.055 * pow ( b, 1 / 2.4 ) - 0.055 : 12.92 * b; r = clamp ( r * 255, 0, 255 ); g = clamp ( g * 255, 0, 255 ); b = clamp ( b * 255, 0, 255 ); return set ( r, g, b ); } vector lab2rgb ( vector lab ) { return xyz2rgb ( lab2xyz ( lab ) ); } vector lch2rgb ( vector lch ) { return lab2rgb ( lch2lab ( lch ) ); } // Shortest path interpolation for HSV/HSL color models // SESI's implementation sometimes returns the shortest, sometimes the longest path vector blendHsvHsl ( vector c0; vector c1; float amount ) { vector diff = c1 - c0; if ( diff.x > 0.5 ) diff.x -= 1; else if ( diff.x < -0.5 ) diff.x += 1; return c0 + diff * amount; } // Shortest path interpolation for LAB/LCH color models vector blendLabLch ( vector c0; vector c1; float amount ) { vector diff = c1 - c0; if ( diff.z > 180 ) diff.z -= 360; else if ( diff.z < -180 ) diff.z += 360; return c0 + diff * amount; } vector blendColor ( vector a; vector b; float amount; int sourceSpace; int blendingSpace ) { vector c = a; vector d = b; vector f = 0; string spaces [ ] = array ( "cspace:rgb", "cspace:hsl", "cspace:hsv", "cspace:XYZ", "cspace::tmi", "cspace:Lab" ); if ( blendingSpace == 5 ) // LAB { if ( sourceSpace == 3 ) // XYZ { c = xyz2lab ( c ); d = xyz2lab ( d ); } else if ( sourceSpace == 6 ) // LCH { c = lch2lab ( c ); d = lch2lab ( d ); } else if ( sourceSpace != 5 ) // not LAB { if ( sourceSpace != 0 ) // not RGB { c = ctransform ( spaces [ sourceSpace ], "cspace:rgb", c ); d = ctransform ( spaces [ sourceSpace ], "cspace:rgb", d ); } c = rgb2lab ( c ); d = rgb2lab ( d ); } f = blendLabLch ( c, d, amount ); if ( sourceSpace == 3 ) // XYZ f = lab2xyz ( f ); else if ( sourceSpace == 6 ) // LCH f = lab2lch ( f ); else if ( sourceSpace != 6 ) // not LCH { f = lab2rgb ( f ); if ( sourceSpace != 0 ) // not RGB f = ctransform ( "cspace:rgb", spaces [ sourceSpace ], f ); } } else if ( blendingSpace == 6 ) // LCH { if ( sourceSpace == 3 ) // XYZ { c = xyz2lch ( c ); d = xyz2lch ( d ); } else if ( sourceSpace == 5 ) // LAB { c = lab2lch ( c ); d = lab2lch ( d ); } else if ( sourceSpace != 6 ) // not LCH { if ( sourceSpace != 0 ) // not RGB { c = ctransform ( spaces [ sourceSpace ], "cspace:rgb", c ); d = ctransform ( spaces [ sourceSpace ], "cspace:rgb", d ); } c = rgb2lch ( c ); d = rgb2lch ( d ); } f = blendLabLch ( c, d, amount ); if ( sourceSpace == 3 ) // XYZ f = lch2xyz ( f ); else if ( sourceSpace == 5 ) // LAB f = lch2lab ( f ); else if ( sourceSpace != 6 ) // not LCH { f = lch2rgb ( f ); if ( sourceSpace != 0 ) // not RGB f = ctransform ( "cspace:rgb", spaces [ sourceSpace ], f ); } } else { c = ctransform ( spaces [ sourceSpace ], spaces [ blendingSpace ], c ); d = ctransform ( spaces [ sourceSpace ], spaces [ blendingSpace ], d ); if ( blendingSpace == 1 || blendingSpace == 2 ) // Shortest path blending for HSV & HSL f = blendHsvHsl ( c, d, amount ); else f = c + ( d - c ) * amount; f = ctransform ( spaces [ blendingSpace ], spaces [ sourceSpace ], f ); } return f; } $cnew = blendColor ( $c0, $c1, $amount, $source, $blending ); }
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]
youtube.com/@pragmaticvfx | patreon.com/animatrix | pragmaticvfx.gumroad.com
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]
youtube.com/@pragmaticvfx | patreon.com/animatrix | pragmaticvfx.gumroad.com
- cncverkstad
- Member
- 117 posts
- Joined: Aug. 2017
- Offline
- tamte
- Member
- 8583 posts
- Joined: July 2007
- Online
-
- Quick Links