#! /Applications/The Foundry/Nuke9.0v4/Nuke9.0v4.app/Contents/MacOS//libnuke-9.0.4.dylib -nx version 9.0 v4 define_window_layout_xml { } Root { inputs 0 name /Volumes/BOOTCAMP/work/client/hpd/code/public/general/blink/scripts/LUTApply.nk format "2048 1556 0 0 2048 1556 1 2K_Super_35(full-ap)" proxy_type scale proxy_format "1024 778 0 0 1024 778 1 1K_Super_35(full-ap)" } BackdropNode { inputs 0 name BackdropNode2 tile_color 0x4a7979ff label "Author LUT" note_font_size 42 xpos -1904 ypos 1237 bdwidth 708 bdheight 1796 z_order -1 } BackdropNode { inputs 0 name BackdropNode7 tile_color 0x7171c600 label "Validate LUT" note_font_size 42 xpos -1174 ypos 1237 bdwidth 1277 bdheight 1797 z_order -1 } BackdropNode { inputs 0 name BackdropNode10 tile_color 0x8e388e00 label "2. Put Grade Here" note_font_size 42 xpos -1829 ypos 1540 bdwidth 565 bdheight 447 } BackdropNode { inputs 0 name BackdropNode17 tile_color 0xa4a4a4ff label "LUT Apply example" note_font_size 42 xpos -1916 ypos 1073 bdwidth 2040 bdheight 142 } BackdropNode { inputs 0 name BackdropNode18 tile_color 0x7171c600 label "4. Write Grade LUT" note_font_size 42 xpos -1828 ypos 2183 bdwidth 563 bdheight 116 } BackdropNode { inputs 0 name BackdropNode21 tile_color 0x747480ff label "3. Compare Grade from Nodes and Grade from LUTApply\n- If the differences are too great,\n--- Increasing the LUT resolution back in Step 1.\n--- Write LUT (Step 4) if all looks good" note_font_size 42 xpos -1124 ypos 1317 bdwidth 1115 bdheight 827 } BackdropNode { inputs 0 name BackdropNode22 tile_color 0x6e705aff label "1. Choose the LUT resolution" note_font_size 42 xpos -1831 ypos 1302 bdwidth 568 bdheight 229 } BackdropNode { inputs 0 name BackdropNode23 tile_color 0x8e7f8eff label "Example Grade" note_font_size 42 xpos -1764 ypos 1609 bdwidth 419 bdheight 336 } BackdropNode { inputs 0 name BackdropNode24 tile_color 0x8e7f8eff label Footage note_font_size 42 xpos -770 ypos 1536 bdwidth 398 bdheight 141 } BackdropNode { inputs 0 name BackdropNode25 tile_color 0x8e7f8eff label LUTApply note_font_size 42 xpos -985 ypos 1864 bdwidth 398 bdheight 141 } BackdropNode { inputs 0 name BackdropNode3 tile_color 0x747480ff label "5. Compare Grade from LUTApply and \nGrade from loaded LUT\n- Images should match exactly\n- Verify these OCIOFileTransform settings:\n--- direction: forward\n--- interpolation: tetrahedral\n--- working space: raw" note_font_size 42 xpos -1124 ypos 2177 bdwidth 1115 bdheight 827 } BackdropNode { inputs 0 name BackdropNode4 tile_color 0x8e7f8eff label Footage note_font_size 42 xpos -665 ypos 2535 bdwidth 197 bdheight 134 } BackdropNode { inputs 0 name BackdropNode5 tile_color 0x8e7f8eff label LUTApply note_font_size 42 xpos -940 ypos 2729 bdwidth 398 bdheight 141 } BackdropNode { inputs 0 name BackdropNode1 tile_color 0xaaaaaa00 label "Duplicate / Clone the grade" note_font_size 42 xpos -510 ypos 1711 bdwidth 480 bdheight 300 z_order 1 } BackdropNode { inputs 0 name BackdropNode6 tile_color 0xaaaaaa00 label "OCIO LUT" note_font_size 42 xpos -512 ypos 2726 bdwidth 447 bdheight 147 z_order 1 } ColorWheel { inputs 0 gamma 0.45 name ColorWheel2 xpos -614 ypos 1570 } Dot { name Dot21 xpos -580 ypos 1656 } set N2a1503e0 [stack 0] Dot { name Dot3 xpos -580 ypos 2615 } set N212f0940 [stack 0] OCIOFileTransform { file /Volumes/BOOTCAMP/work/client/hpd/code/public/general/blink/scripts/exampleGrade.3dl interpolation tetrahedral working_space raw name OCIOFileTransform2 xpos -328 ypos 2820 } CMSTestPattern { inputs 0 cube_size 17 name CMSTestPattern9 xpos -1610 ypos 1408 } set N2a114d60 [stack 0] Dot { name Dot19 xpos -1576 ypos 1498 } set N2a11af10 [stack 0] Grade { white {0.583485 0.531876 1 1} white_panelDropped true multiply {1 1 1 1} gamma 1.2 name Grade2 xpos -1610 ypos 1780 } set C2a12a5e0 [stack 0] Saturation { saturation 0.75 name Saturation4 xpos -1610 ypos 1804 } set C2a1308c0 [stack 0] Dot { name Dot1 xpos -1576 ypos 1966 } set N2c5c6580 [stack 0] Dot { name Dot4 xpos -1046 ypos 1966 } set N2c570c60 [stack 0] Dot { name Dot5 xpos -1046 ypos 2713 } push $N212f0940 BlinkScript { inputs 2 kernelSourceFile /Volumes/BOOTCAMP/work/client/hpd/code/public/general/blink/LUTApply.blink KernelDescription "1 \"LUTApplyKernel\" iterate pixelWise b9b9b75f844d32a217ac98b2629aaee332a5ac1102535c30004a41d380e5f8fd 3 \"src\" Read Random \"cmsPattern\" Read Random \"dst\" Write Point 1 \"interpolation\" Int 1 AgAAAA==" kernelSource "//\n// Copyright (c) 2014-2015 Haarm-Pieter Duiker \n//\n\n//\n// A kernel that will apply 3d LUT to an image. The 3d LUT is represented as the Nuke cmsTestPattern\n//\n\n//\n// Map from a 3D LUT position to 2D pixel coordinate in the CMSTestPattern image\n//\nint2 position3dToNukePosition(int3 pos, int width, int height, int nukeBlockSize, int lutResolution) \{\n int2 position;\n\n int pixel = (pos.z*lutResolution*lutResolution + pos.y*lutResolution + pos.x);\n\n position.x = (pixel%(width/nukeBlockSize))*nukeBlockSize;\n position.y = (pixel/(width/nukeBlockSize))*nukeBlockSize;\n\n // Put the position in the middle of the nukeBlockSize x nukeBlockSize block\n position += nukeBlockSize/2;\n\n return position;\n\}\n\n// Utility\nfloat4 mix(float4 a, float4 b, float f) \{\n float4 mixed;\n mixed.x = a.x*(1.f - f) + b.x*f;\n mixed.y = a.y*(1.f - f) + b.y*f;\n mixed.z = a.z*(1.f - f) + b.z*f;\n mixed.w = a.w*(1.f - f) + b.w*f;\n return mixed; \n\}\n\n//\n// kernel\n//\nkernel LUTApplyKernel : public ImageComputationKernel\n\{\n Image src;\n Image cmsPattern;\n Image dst;\n\n param:\n int interpolation;\n\n local:\n int lutResolution;\n int nukeBlockSize;\n\n void define() \{\n // unused for now. \n defineParam(interpolation, \"interpolation\", 2);\n \}\n\n void init() \{\n // The Nuke CMSTestPattern node generates 7x7 pixel blocks for each LUT entry\n nukeBlockSize = 7;\n float pixels = cmsPattern.bounds.width() * cmsPattern.bounds.height() / (nukeBlockSize * nukeBlockSize);\n lutResolution = int(floor(pow(pixels, 0.333333333334f)));\n \}\n\n void process(int2 pos) \{\n SampleType(cmsPattern) cmsSample;\n\n // Sample the src image\n SampleType(src) srcSample;\n srcSample = src(pos.x, pos.y);\n\n // Use the 3D LUT to find the new value\n \n // Nearest point\n if( interpolation == 0 ) \{\n int3 srcLUTPosition;\n srcLUTPosition.x = round(clamp(srcSample.x, 0.0f, 1.0f) * (lutResolution-1));\n srcLUTPosition.y = round(clamp(srcSample.y, 0.0f, 1.0f) * (lutResolution-1));\n srcLUTPosition.z = round(clamp(srcSample.z, 0.0f, 1.0f) * (lutResolution-1));\n\n int2 cmsSamplePosition;\n cmsSamplePosition = position3dToNukePosition(srcLUTPosition, \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n\n cmsSample = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n \} // nearest\n\n // Tri-linear interpolation \n else if( interpolation == 1 ) \{\n float3 srcSample3;\n srcSample3.x = srcSample.x;\n srcSample3.y = srcSample.y;\n srcSample3.z = srcSample.z;\n\n srcSample3 = clamp(srcSample3, float3(0.f), float3(1.f));\n\n // index values interpolation factor for RGB\n float indexRf = (srcSample3.x * (lutResolution-1));\n int indexR = int(floor(indexRf));\n float interpR = indexRf - indexR;\n float indexRfb = floor(indexRf) / (lutResolution-1);\n\n float indexGf = (srcSample3.y * (lutResolution-1));\n int indexG = int(floor(indexGf));\n float interpG = indexGf - indexG;\n float indexGfb = floor(indexGf) / (lutResolution-1);\n\n float indexBf = (srcSample3.z * (lutResolution-1));\n int indexB = int(floor(indexBf));\n float interpB = indexBf - indexB;\n float indexBfb = floor(indexBf) / (lutResolution-1);\n\n SampleType(cmsPattern) cmsSamples\[8];\n int2 cmsSamplePosition;\n\n // sample r, g, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG , indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[0] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r, g, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG , indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[1] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r, g+1, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG + 1, indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[2] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r, g+1, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG + 1, indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[3] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG , indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[4] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG , indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[5] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g+1, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG + 1, indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[6] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g+1, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG + 1, indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[7] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // Interpolate along the 4 lines in B\n cmsSamples\[0] = mix(cmsSamples\[0], cmsSamples\[1], interpB);\n cmsSamples\[2] = mix(cmsSamples\[2], cmsSamples\[3], interpB);\n cmsSamples\[4] = mix(cmsSamples\[4], cmsSamples\[5], interpB);\n cmsSamples\[6] = mix(cmsSamples\[6], cmsSamples\[7], interpB);\n \n // Interpolate along the 2 lines in G\n cmsSamples\[0] = mix(cmsSamples\[0], cmsSamples\[2], interpG);\n cmsSamples\[4] = mix(cmsSamples\[4], cmsSamples\[6], interpG);\n\n // Interpolate along the 1 line in R\n cmsSamples\[0] = mix(cmsSamples\[0], cmsSamples\[4], interpR);\n\n cmsSample = cmsSamples\[0];\n \} // tri-linear\n\n // Tetrahedral interpolation\n else if( interpolation == 2 ) \{\n float3 srcSample3;\n srcSample3.x = srcSample.x;\n srcSample3.y = srcSample.y;\n srcSample3.z = srcSample.z;\n\n srcSample3 = clamp(srcSample3, float3(0.f), float3(1.f));\n\n // index values interpolation factor for RGB\n float indexRf = (srcSample3.x * (lutResolution-1));\n int indexR = int(floor(indexRf));\n float interpR = indexRf - indexR;\n float indexRfb = floor(indexRf) / (lutResolution-1);\n\n float indexGf = (srcSample3.y * (lutResolution-1));\n int indexG = int(floor(indexGf));\n float interpG = indexGf - indexG;\n float indexGfb = floor(indexGf) / (lutResolution-1);\n\n float indexBf = (srcSample3.z * (lutResolution-1));\n int indexB = int(floor(indexBf));\n float interpB = indexBf - indexB;\n float indexBfb = floor(indexBf) / (lutResolution-1);\n\n SampleType(cmsPattern) cmsSamples\[8];\n int2 cmsSamplePosition;\n\n // sample r, g, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG , indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[0] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r, g, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG , indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[1] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r, g+1, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG + 1, indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[2] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r, g+1, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG + 1, indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[3] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG , indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[4] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG , indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[5] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g+1, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG + 1, indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[6] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g+1, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG + 1, indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[7] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // Tetrahedral interoplation, as described by:\n // http://www.filmlight.ltd.uk/pdf/whitepapers/FL-TL-TN-0057-SoftwareLib.pdf\n // http://blogs.mathworks.com/steve/2006/11/24/tetrahedral-interpolation-for-colorspace-conversion/\n // http://www.hpl.hp.com/techreports/98/HPL-98-95.html\n // Reference implementation from OCIO\n // https://github.com/imageworks/OpenColorIO/blob/master/src/core/Lut3DOp.cpp#L294\n\n // Rebind for consistency with Truelight paper\n float fx = interpR;\n float fy = interpG;\n float fz = interpB;\n\n SampleType(cmsPattern) startPos\[8];\n startPos\[0] = cmsSamples\[0];\n startPos\[1] = cmsSamples\[1];\n startPos\[2] = cmsSamples\[2];\n startPos\[3] = cmsSamples\[3];\n startPos\[4] = cmsSamples\[4];\n startPos\[5] = cmsSamples\[5];\n startPos\[6] = cmsSamples\[6];\n startPos\[7] = cmsSamples\[7];\n\n SampleType(cmsPattern) rgbaBuffer;\n\n // Compute index into LUT for surrounding corners\n const int n000 = 0;\n const int n100 = 4;\n const int n010 = 2;\n const int n001 = 1;\n const int n110 = 6;\n const int n101 = 5;\n const int n011 = 3;\n const int n111 = 7;\n\n if (fx > fy) \{\n if (fy > fz) \{\n rgbaBuffer.x =\n (1-fx) * startPos\[n000].x +\n (fx-fy) * startPos\[n100].x +\n (fy-fz) * startPos\[n110].x +\n (fz) * startPos\[n111].x;\n\n rgbaBuffer.y =\n (1-fx) * startPos\[n000].y +\n (fx-fy) * startPos\[n100].y +\n (fy-fz) * startPos\[n110].y +\n (fz) * startPos\[n111].y;\n\n rgbaBuffer.z =\n (1-fx) * startPos\[n000].z +\n (fx-fy) * startPos\[n100].z +\n (fy-fz) * startPos\[n110].z +\n (fz) * startPos\[n111].z;\n \}\n else if (fx > fz)\n \{\n rgbaBuffer.x =\n (1-fx) * startPos\[n000].x +\n (fx-fz) * startPos\[n100].x +\n (fz-fy) * startPos\[n101].x +\n (fy) * startPos\[n111].x;\n\n rgbaBuffer.y =\n (1-fx) * startPos\[n000].y +\n (fx-fz) * startPos\[n100].y +\n (fz-fy) * startPos\[n101].y +\n (fy) * startPos\[n111].y;\n\n rgbaBuffer.z =\n (1-fx) * startPos\[n000].z +\n (fx-fz) * startPos\[n100].z +\n (fz-fy) * startPos\[n101].z +\n (fy) * startPos\[n111].z;\n \}\n else\n \{\n rgbaBuffer.x =\n (1-fz) * startPos\[n000].x +\n (fz-fx) * startPos\[n001].x +\n (fx-fy) * startPos\[n101].x +\n (fy) * startPos\[n111].x;\n\n rgbaBuffer.y =\n (1-fz) * startPos\[n000].y +\n (fz-fx) * startPos\[n001].y +\n (fx-fy) * startPos\[n101].y +\n (fy) * startPos\[n111].y;\n\n rgbaBuffer.z =\n (1-fz) * startPos\[n000].z +\n (fz-fx) * startPos\[n001].z +\n (fx-fy) * startPos\[n101].z +\n (fy) * startPos\[n111].z;\n \}\n \}\n else\n \{\n if (fz > fy)\n \{\n rgbaBuffer.x =\n (1-fz) * startPos\[n000].x +\n (fz-fy) * startPos\[n001].x +\n (fy-fx) * startPos\[n011].x +\n (fx) * startPos\[n111].x;\n\n rgbaBuffer.y =\n (1-fz) * startPos\[n000].y +\n (fz-fy) * startPos\[n001].y +\n (fy-fx) * startPos\[n011].y +\n (fx) * startPos\[n111].y;\n\n rgbaBuffer.z =\n (1-fz) * startPos\[n000].z +\n (fz-fy) * startPos\[n001].z +\n (fy-fx) * startPos\[n011].z +\n (fx) * startPos\[n111].z;\n \}\n else if (fz > fx)\n \{\n rgbaBuffer.x =\n (1-fy) * startPos\[n000].x +\n (fy-fz) * startPos\[n010].x +\n (fz-fx) * startPos\[n011].x +\n (fx) * startPos\[n111].x;\n\n rgbaBuffer.y =\n (1-fy) * startPos\[n000].y +\n (fy-fz) * startPos\[n010].y +\n (fz-fx) * startPos\[n011].y +\n (fx) * startPos\[n111].y;\n\n rgbaBuffer.z =\n (1-fy) * startPos\[n000].z +\n (fy-fz) * startPos\[n010].z +\n (fz-fx) * startPos\[n011].z +\n (fx) * startPos\[n111].z;\n \}\n else\n \{\n rgbaBuffer.x =\n (1-fy) * startPos\[n000].x +\n (fy-fx) * startPos\[n010].x +\n (fx-fz) * startPos\[n110].x +\n (fz) * startPos\[n111].x;\n\n rgbaBuffer.y =\n (1-fy) * startPos\[n000].y +\n (fy-fx) * startPos\[n010].y +\n (fx-fz) * startPos\[n110].y +\n (fz) * startPos\[n111].y;\n\n rgbaBuffer.z =\n (1-fy) * startPos\[n000].z +\n (fy-fx) * startPos\[n010].z +\n (fx-fz) * startPos\[n110].z +\n (fz) * startPos\[n111].z;\n \}\n \}\n\n cmsSample = rgbaBuffer;\n\n \} // tetrahedral\n\n // Write the new value to dst\n SampleType(dst) t;\n t.x = cmsSample.x;\n t.y = cmsSample.y;\n t.z = cmsSample.z;\n\n dst() = t;\n \}\n\};\n" rebuild "" maxTileLines 100 name BlinkScript1 xpos -794 ypos 2815 } Difference { inputs 2 gain 10000 output rgba.red name Difference3 xpos -564 ypos 2909 } Shuffle { green red blue red name Shuffle4 xpos -564 ypos 2941 } push $N2a1503e0 clone $C2a12a5e0 { xpos -321 ypos 1854 selected false } clone $C2a1308c0 { xpos -321 ypos 1878 selected false } push $N2c570c60 push $N2a1503e0 BlinkScript { inputs 2 kernelSourceFile /Volumes/BOOTCAMP/work/client/hpd/code/public/general/blink/LUTApply.blink KernelDescription "1 \"LUTApplyKernel\" iterate pixelWise b9b9b75f844d32a217ac98b2629aaee332a5ac1102535c30004a41d380e5f8fd 3 \"src\" Read Random \"cmsPattern\" Read Random \"dst\" Write Point 1 \"interpolation\" Int 1 AgAAAA==" kernelSource "//\n// Copyright (c) 2014-2015 Haarm-Pieter Duiker \n//\n\n//\n// A kernel that will apply 3d LUT to an image. The 3d LUT is represented as the Nuke cmsTestPattern\n//\n\n//\n// Map from a 3D LUT position to 2D pixel coordinate in the CMSTestPattern image\n//\nint2 position3dToNukePosition(int3 pos, int width, int height, int nukeBlockSize, int lutResolution) \{\n int2 position;\n\n int pixel = (pos.z*lutResolution*lutResolution + pos.y*lutResolution + pos.x);\n\n position.x = (pixel%(width/nukeBlockSize))*nukeBlockSize;\n position.y = (pixel/(width/nukeBlockSize))*nukeBlockSize;\n\n // Put the position in the middle of the nukeBlockSize x nukeBlockSize block\n position += nukeBlockSize/2;\n\n return position;\n\}\n\n// Utility\nfloat4 mix(float4 a, float4 b, float f) \{\n float4 mixed;\n mixed.x = a.x*(1.f - f) + b.x*f;\n mixed.y = a.y*(1.f - f) + b.y*f;\n mixed.z = a.z*(1.f - f) + b.z*f;\n mixed.w = a.w*(1.f - f) + b.w*f;\n return mixed; \n\}\n\n//\n// kernel\n//\nkernel LUTApplyKernel : public ImageComputationKernel\n\{\n Image src;\n Image cmsPattern;\n Image dst;\n\n param:\n int interpolation;\n\n local:\n int lutResolution;\n int nukeBlockSize;\n\n void define() \{\n // unused for now. \n defineParam(interpolation, \"interpolation\", 2);\n \}\n\n void init() \{\n // The Nuke CMSTestPattern node generates 7x7 pixel blocks for each LUT entry\n nukeBlockSize = 7;\n float pixels = cmsPattern.bounds.width() * cmsPattern.bounds.height() / (nukeBlockSize * nukeBlockSize);\n lutResolution = int(floor(pow(pixels, 0.333333333334f)));\n \}\n\n void process(int2 pos) \{\n SampleType(cmsPattern) cmsSample;\n\n // Sample the src image\n SampleType(src) srcSample;\n srcSample = src(pos.x, pos.y);\n\n // Use the 3D LUT to find the new value\n \n // Nearest point\n if( interpolation == 0 ) \{\n int3 srcLUTPosition;\n srcLUTPosition.x = round(clamp(srcSample.x, 0.0f, 1.0f) * (lutResolution-1));\n srcLUTPosition.y = round(clamp(srcSample.y, 0.0f, 1.0f) * (lutResolution-1));\n srcLUTPosition.z = round(clamp(srcSample.z, 0.0f, 1.0f) * (lutResolution-1));\n\n int2 cmsSamplePosition;\n cmsSamplePosition = position3dToNukePosition(srcLUTPosition, \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n\n cmsSample = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n \} // nearest\n\n // Tri-linear interpolation \n else if( interpolation == 1 ) \{\n float3 srcSample3;\n srcSample3.x = srcSample.x;\n srcSample3.y = srcSample.y;\n srcSample3.z = srcSample.z;\n\n srcSample3 = clamp(srcSample3, float3(0.f), float3(1.f));\n\n // index values interpolation factor for RGB\n float indexRf = (srcSample3.x * (lutResolution-1));\n int indexR = int(floor(indexRf));\n float interpR = indexRf - indexR;\n float indexRfb = floor(indexRf) / (lutResolution-1);\n\n float indexGf = (srcSample3.y * (lutResolution-1));\n int indexG = int(floor(indexGf));\n float interpG = indexGf - indexG;\n float indexGfb = floor(indexGf) / (lutResolution-1);\n\n float indexBf = (srcSample3.z * (lutResolution-1));\n int indexB = int(floor(indexBf));\n float interpB = indexBf - indexB;\n float indexBfb = floor(indexBf) / (lutResolution-1);\n\n SampleType(cmsPattern) cmsSamples\[8];\n int2 cmsSamplePosition;\n\n // sample r, g, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG , indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[0] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r, g, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG , indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[1] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r, g+1, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG + 1, indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[2] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r, g+1, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG + 1, indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[3] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG , indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[4] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG , indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[5] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g+1, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG + 1, indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[6] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g+1, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG + 1, indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[7] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // Interpolate along the 4 lines in B\n cmsSamples\[0] = mix(cmsSamples\[0], cmsSamples\[1], interpB);\n cmsSamples\[2] = mix(cmsSamples\[2], cmsSamples\[3], interpB);\n cmsSamples\[4] = mix(cmsSamples\[4], cmsSamples\[5], interpB);\n cmsSamples\[6] = mix(cmsSamples\[6], cmsSamples\[7], interpB);\n \n // Interpolate along the 2 lines in G\n cmsSamples\[0] = mix(cmsSamples\[0], cmsSamples\[2], interpG);\n cmsSamples\[4] = mix(cmsSamples\[4], cmsSamples\[6], interpG);\n\n // Interpolate along the 1 line in R\n cmsSamples\[0] = mix(cmsSamples\[0], cmsSamples\[4], interpR);\n\n cmsSample = cmsSamples\[0];\n \} // tri-linear\n\n // Tetrahedral interpolation\n else if( interpolation == 2 ) \{\n float3 srcSample3;\n srcSample3.x = srcSample.x;\n srcSample3.y = srcSample.y;\n srcSample3.z = srcSample.z;\n\n srcSample3 = clamp(srcSample3, float3(0.f), float3(1.f));\n\n // index values interpolation factor for RGB\n float indexRf = (srcSample3.x * (lutResolution-1));\n int indexR = int(floor(indexRf));\n float interpR = indexRf - indexR;\n float indexRfb = floor(indexRf) / (lutResolution-1);\n\n float indexGf = (srcSample3.y * (lutResolution-1));\n int indexG = int(floor(indexGf));\n float interpG = indexGf - indexG;\n float indexGfb = floor(indexGf) / (lutResolution-1);\n\n float indexBf = (srcSample3.z * (lutResolution-1));\n int indexB = int(floor(indexBf));\n float interpB = indexBf - indexB;\n float indexBfb = floor(indexBf) / (lutResolution-1);\n\n SampleType(cmsPattern) cmsSamples\[8];\n int2 cmsSamplePosition;\n\n // sample r, g, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG , indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[0] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r, g, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG , indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[1] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r, g+1, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG + 1, indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[2] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r, g+1, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR , indexG + 1, indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[3] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG , indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[4] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG , indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[5] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g+1, b\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG + 1, indexB ), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[6] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // sample r+1, g+1, b+1\n cmsSamplePosition = position3dToNukePosition(int3(indexR + 1, indexG + 1, indexB + 1), \n cmsPattern.bounds.width(), cmsPattern.bounds.height(), nukeBlockSize, lutResolution);\n cmsSamples\[7] = cmsPattern(cmsSamplePosition.x, cmsSamplePosition.y);\n\n // Tetrahedral interoplation, as described by:\n // http://www.filmlight.ltd.uk/pdf/whitepapers/FL-TL-TN-0057-SoftwareLib.pdf\n // http://blogs.mathworks.com/steve/2006/11/24/tetrahedral-interpolation-for-colorspace-conversion/\n // http://www.hpl.hp.com/techreports/98/HPL-98-95.html\n // Reference implementation from OCIO\n // https://github.com/imageworks/OpenColorIO/blob/master/src/core/Lut3DOp.cpp#L294\n\n // Rebind for consistency with Truelight paper\n float fx = interpR;\n float fy = interpG;\n float fz = interpB;\n\n SampleType(cmsPattern) startPos\[8];\n startPos\[0] = cmsSamples\[0];\n startPos\[1] = cmsSamples\[1];\n startPos\[2] = cmsSamples\[2];\n startPos\[3] = cmsSamples\[3];\n startPos\[4] = cmsSamples\[4];\n startPos\[5] = cmsSamples\[5];\n startPos\[6] = cmsSamples\[6];\n startPos\[7] = cmsSamples\[7];\n\n SampleType(cmsPattern) rgbaBuffer;\n\n // Compute index into LUT for surrounding corners\n const int n000 = 0;\n const int n100 = 4;\n const int n010 = 2;\n const int n001 = 1;\n const int n110 = 6;\n const int n101 = 5;\n const int n011 = 3;\n const int n111 = 7;\n\n if (fx > fy) \{\n if (fy > fz) \{\n rgbaBuffer.x =\n (1-fx) * startPos\[n000].x +\n (fx-fy) * startPos\[n100].x +\n (fy-fz) * startPos\[n110].x +\n (fz) * startPos\[n111].x;\n\n rgbaBuffer.y =\n (1-fx) * startPos\[n000].y +\n (fx-fy) * startPos\[n100].y +\n (fy-fz) * startPos\[n110].y +\n (fz) * startPos\[n111].y;\n\n rgbaBuffer.z =\n (1-fx) * startPos\[n000].z +\n (fx-fy) * startPos\[n100].z +\n (fy-fz) * startPos\[n110].z +\n (fz) * startPos\[n111].z;\n \}\n else if (fx > fz)\n \{\n rgbaBuffer.x =\n (1-fx) * startPos\[n000].x +\n (fx-fz) * startPos\[n100].x +\n (fz-fy) * startPos\[n101].x +\n (fy) * startPos\[n111].x;\n\n rgbaBuffer.y =\n (1-fx) * startPos\[n000].y +\n (fx-fz) * startPos\[n100].y +\n (fz-fy) * startPos\[n101].y +\n (fy) * startPos\[n111].y;\n\n rgbaBuffer.z =\n (1-fx) * startPos\[n000].z +\n (fx-fz) * startPos\[n100].z +\n (fz-fy) * startPos\[n101].z +\n (fy) * startPos\[n111].z;\n \}\n else\n \{\n rgbaBuffer.x =\n (1-fz) * startPos\[n000].x +\n (fz-fx) * startPos\[n001].x +\n (fx-fy) * startPos\[n101].x +\n (fy) * startPos\[n111].x;\n\n rgbaBuffer.y =\n (1-fz) * startPos\[n000].y +\n (fz-fx) * startPos\[n001].y +\n (fx-fy) * startPos\[n101].y +\n (fy) * startPos\[n111].y;\n\n rgbaBuffer.z =\n (1-fz) * startPos\[n000].z +\n (fz-fx) * startPos\[n001].z +\n (fx-fy) * startPos\[n101].z +\n (fy) * startPos\[n111].z;\n \}\n \}\n else\n \{\n if (fz > fy)\n \{\n rgbaBuffer.x =\n (1-fz) * startPos\[n000].x +\n (fz-fy) * startPos\[n001].x +\n (fy-fx) * startPos\[n011].x +\n (fx) * startPos\[n111].x;\n\n rgbaBuffer.y =\n (1-fz) * startPos\[n000].y +\n (fz-fy) * startPos\[n001].y +\n (fy-fx) * startPos\[n011].y +\n (fx) * startPos\[n111].y;\n\n rgbaBuffer.z =\n (1-fz) * startPos\[n000].z +\n (fz-fy) * startPos\[n001].z +\n (fy-fx) * startPos\[n011].z +\n (fx) * startPos\[n111].z;\n \}\n else if (fz > fx)\n \{\n rgbaBuffer.x =\n (1-fy) * startPos\[n000].x +\n (fy-fz) * startPos\[n010].x +\n (fz-fx) * startPos\[n011].x +\n (fx) * startPos\[n111].x;\n\n rgbaBuffer.y =\n (1-fy) * startPos\[n000].y +\n (fy-fz) * startPos\[n010].y +\n (fz-fx) * startPos\[n011].y +\n (fx) * startPos\[n111].y;\n\n rgbaBuffer.z =\n (1-fy) * startPos\[n000].z +\n (fy-fz) * startPos\[n010].z +\n (fz-fx) * startPos\[n011].z +\n (fx) * startPos\[n111].z;\n \}\n else\n \{\n rgbaBuffer.x =\n (1-fy) * startPos\[n000].x +\n (fy-fx) * startPos\[n010].x +\n (fx-fz) * startPos\[n110].x +\n (fz) * startPos\[n111].x;\n\n rgbaBuffer.y =\n (1-fy) * startPos\[n000].y +\n (fy-fx) * startPos\[n010].y +\n (fx-fz) * startPos\[n110].y +\n (fz) * startPos\[n111].y;\n\n rgbaBuffer.z =\n (1-fy) * startPos\[n000].z +\n (fy-fx) * startPos\[n010].z +\n (fx-fz) * startPos\[n110].z +\n (fz) * startPos\[n111].z;\n \}\n \}\n\n cmsSample = rgbaBuffer;\n\n \} // tetrahedral\n\n // Write the new value to dst\n SampleType(dst) t;\n t.x = cmsSample.x;\n t.y = cmsSample.y;\n t.z = cmsSample.z;\n\n dst() = t;\n \}\n\};\n" rebuild "" maxTileLines 100 name BlinkScript11 xpos -833 ypos 1959 } set N2a15d7d0 [stack 0] Difference { inputs 2 gain 10000 output rgba.red name Difference9 xpos -510 ypos 2065 } Shuffle { green red blue red name Shuffle3 xpos -510 ypos 2097 } push $N2a15d7d0 push $N2a114d60 Viewer { inputs 3 frame_range 1-100 name Viewer1 xpos -1997 ypos 1447 } push $N2a11af10 Reformat { format "512 512 0 0 512 512 1 square_512" name Reformat6 xpos -2154 ypos 1491 } Write { file /Volumes/BOOTCAMP/work/client/hpd/code/public/general/blink/scripts/LUTApply_identity.jpg raw true file_type jpeg _jpeg_quality 1 _jpeg_sub_sampling 4:4:4 checkHashOnRead false version 4 name Write5 xpos -2154 ypos 1523 } push $N2c5c6580 GenerateLUT { file /Volumes/BOOTCAMP/work/client/hpd/code/public/general/blink/scripts/LUTApply_exampleGrade.3dl file_type .3dl name GenerateLUT12 xpos -1610 ypos 2255 } Reformat { format "512 512 0 0 512 512 1 square_512" name Reformat8 xpos -2109 ypos 2251 } Write { file /Volumes/BOOTCAMP/work/client/hpd/code/public/general/blink/scripts/LUTApply_grade.jpg raw true file_type jpeg _jpeg_quality 1 _jpeg_sub_sampling 4:4:4 checkHashOnRead false version 6 name Write7 xpos -2109 ypos 2283 }