├── ISFparser.toe ├── ISFparser.111.toe ├── assets └── ISF tests+tutorials │ ├── Hexagon.tiff │ ├── Test-Functionality.fs │ ├── Test-IMG_PIXEL.fs │ ├── Test-IMG_THIS_PIXEL.fs │ ├── Test-IMG_THIS_NORM_PIXEL.fs │ ├── Test-IMG_NORM_PIXEL.fs │ ├── Test-Event.fs │ ├── Test-Bool.fs │ ├── _Test-ImportedImage.fs │ ├── Test-Float.fs │ ├── Test-Point.fs │ ├── _Test-PersistentBuffer.fs │ ├── _Test-MyPersistentBuffer.fs │ ├── Test-Long.fs │ ├── Test-Color.fs │ ├── _Test-TempBufferDifferingSizes.fs │ ├── _Test-MultiPassRendering.fs │ ├── _Test-PersistentBufferDifferingSizes.fs │ └── Test-Sampler.fs ├── scripts ├── create_glop.py ├── file_splitter_script_callbacks.py ├── create_buffer.py ├── find_and_replace_script_callbacks.py ├── json_parser_script_callbacks.py └── uniform_maker.py ├── README.md └── .gitattributes /ISFparser.toe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zealtv/TouchDesigner-ISF-parser/HEAD/ISFparser.toe -------------------------------------------------------------------------------- /ISFparser.111.toe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zealtv/TouchDesigner-ISF-parser/HEAD/ISFparser.111.toe -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/Hexagon.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zealtv/TouchDesigner-ISF-parser/HEAD/assets/ISF tests+tutorials/Hexagon.tiff -------------------------------------------------------------------------------- /scripts/create_glop.py: -------------------------------------------------------------------------------- 1 | if op('GLSL'): 2 | op('GLSL').destroy() 3 | 4 | glop = me.parent().create(glslmultiTOP, 'GLSL') 5 | 6 | glop.nodeX = me.nodeX 7 | glop.nodeY = me.nodeY - 100 8 | glop.inputConnectors[0].connect(op('in1')) 9 | op('out1').inputConnectors[0].connect(glop) 10 | glop.par.pdat = 'FRAG_SHADER' -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/Test-Functionality.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "just colors the passed image opaque red, tests basic rendering functionality", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | } 12 | ] 13 | }*/ 14 | 15 | void main() 16 | { 17 | gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 18 | } -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/Test-IMG_PIXEL.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of IMG_PIXEL to fetch a pixel color from an input", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | } 12 | ] 13 | }*/ 14 | 15 | void main() 16 | { 17 | vec4 test = IMG_PIXEL(inputImage, gl_FragCoord.xy); 18 | gl_FragColor = test; 19 | } 20 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/Test-IMG_THIS_PIXEL.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of IMG_THIS_PIXEL to fetch a pixel color from an input", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | } 12 | ] 13 | }*/ 14 | 15 | void main() 16 | { 17 | vec4 test = IMG_THIS_PIXEL(inputImage); 18 | gl_FragColor = test; 19 | } 20 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/Test-IMG_THIS_NORM_PIXEL.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of IMG_THIS_NORM_PIXEL to fetch a pixel color from an input", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | } 12 | ] 13 | }*/ 14 | 15 | void main() 16 | { 17 | vec4 test = IMG_THIS_NORM_PIXEL(inputImage); 18 | gl_FragColor = test; 19 | } 20 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/Test-IMG_NORM_PIXEL.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of IMG_NORM_PIXEL to fetch a pixel color from an input", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | } 12 | ] 13 | }*/ 14 | 15 | void main() 16 | { 17 | vec4 test = IMG_NORM_PIXEL(inputImage, vv_FragNormCoord); 18 | gl_FragColor = test; 19 | } 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TouchDesigner-ISF-parser 2 | ======================== 3 | 4 | This TouchDesigner project parses ISF files converts them to touchdesigner GLSL shaders as well as creating/connecting any necessary operators and declaring uniform variables. 5 | 6 | Some shaders require various amounts of manual tweaking to make touch-compatible. 7 | 8 | Details on the ISF format here: http://vdmx.vidvox.net/blog/isf 9 | Yet to be implemented are multiple passes and image loading. 10 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/Test-Event.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of an event-type input", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX", "OTHER CATEGORY" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | }, 12 | { 13 | "NAME": "flashEvent", 14 | "TYPE": "event" 15 | } 16 | ] 17 | }*/ 18 | 19 | void main() 20 | { 21 | vec4 srcPixel = IMG_THIS_PIXEL(inputImage); 22 | gl_FragColor = (flashEvent==true) ? vec4(1.0,1.0,1.0,1.0) : srcPixel; 23 | } 24 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/Test-Bool.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates a BOOL-type input on an image filter", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | }, 12 | { 13 | "NAME": "flashToggle", 14 | "TYPE": "bool", 15 | "DEFAULT": 1.0 16 | } 17 | ] 18 | }*/ 19 | 20 | void main() 21 | { 22 | vec4 srcPixel = IMG_THIS_PIXEL(inputImage); 23 | gl_FragColor = (flashToggle==true) ? vec4(1.0,1.0,1.0,1.0) : srcPixel; 24 | } 25 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /scripts/file_splitter_script_callbacks.py: -------------------------------------------------------------------------------- 1 | def cook(scriptOP): 2 | scriptOP.clear() 3 | 4 | body = False 5 | 6 | textfile = op('fs_in').text 7 | numChar = len(textfile) 8 | 9 | headStart = textfile.find( '/*' ) 10 | headEnd = textfile.find( '*/' ) 11 | 12 | scriptOP.write( 'number of lines: ', numChar, '\n') 13 | scriptOP.write( 'start of header: ', headStart, '\n') 14 | scriptOP.write( 'end of header: ', headEnd, '\n') 15 | 16 | 17 | 18 | op('header_out').text = textfile[ headStart + 2 : headEnd ] 19 | op('shader_out').text = textfile[ headEnd + 2 : numChar ] 20 | 21 | 22 | return 23 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/_Test-ImportedImage.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of multiple image-type inputs", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | } 12 | ], 13 | "IMPORTED": { 14 | "blendImage": { 15 | "PATH": "Hexagon.tiff" 16 | } 17 | } 18 | }*/ 19 | 20 | void main() 21 | { 22 | vec4 srcPixel = IMG_NORM_PIXEL(inputImage, vv_FragNormCoord); 23 | vec4 blendPixel = IMG_NORM_PIXEL(blendImage, vv_FragNormCoord); 24 | 25 | gl_FragColor = (srcPixel + blendPixel)/2.0; 26 | } 27 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/Test-Float.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of float-type inputs", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | }, 12 | { 13 | "NAME": "level", 14 | "TYPE": "float", 15 | "DEFAULT": 0.5, 16 | "MIN": 0.0, 17 | "MAX": 1.0 18 | } 19 | ] 20 | }*/ 21 | 22 | void main() 23 | { 24 | vec4 srcPixel = IMG_THIS_PIXEL(inputImage); 25 | float luma = (srcPixel.r+srcPixel.g+srcPixel.b)/3.0; 26 | vec4 dstPixel = (luma>level) ? srcPixel : vec4(0,0,0,1); 27 | gl_FragColor = dstPixel; 28 | } 29 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/Test-Point.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of a 2d point-type input", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | }, 12 | { 13 | "NAME": "location", 14 | "TYPE": "point2D", 15 | "DEFAULT": [ 16 | 0, 17 | 0 18 | ] 19 | } 20 | ] 21 | }*/ 22 | 23 | void main() 24 | { 25 | vec4 srcPixel = IMG_THIS_PIXEL(inputImage); 26 | if (abs(gl_FragCoord.xy.x-location.x)<10.0 && abs(gl_FragCoord.xy.y-location.y)<10.0) 27 | gl_FragColor = vec4(1,1,1,1); 28 | else 29 | gl_FragColor = srcPixel; 30 | } 31 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/_Test-PersistentBuffer.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of a persistent buffer to create a motion-blur type effect. also demonstrates the simplest use of steps: a one-step rendering pass", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | }, 12 | { 13 | "NAME": "blurAmount", 14 | "TYPE": "float" 15 | } 16 | ], 17 | "PERSISTENT_BUFFERS": [ 18 | "bufferVariableNameA" 19 | ], 20 | "PASSES": [ 21 | { 22 | "TARGET": "bufferVariableNameA", 23 | "FLOAT": true 24 | } 25 | ] 26 | 27 | }*/ 28 | 29 | void main() 30 | { 31 | vec4 freshPixel = IMG_THIS_PIXEL(inputImage); 32 | vec4 stalePixel = IMG_THIS_PIXEL(bufferVariableNameA); 33 | gl_FragColor = mix(freshPixel,stalePixel,blurAmount); 34 | } 35 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/_Test-MyPersistentBuffer.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of a persistent buffer to create a motion-blur type effect. also demonstrates the simplest use of steps: a one-step rendering pass", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | }, 12 | { 13 | "NAME": "blurAmount", 14 | "TYPE": "float" 15 | } 16 | ], 17 | "PERSISTENT_BUFFERS": [ 18 | "bufferVariableNameA", "bufferVariableNameB" 19 | ] 20 | 21 | 22 | }*/ 23 | 24 | void main() 25 | { 26 | vec4 freshPixel = IMG_THIS_PIXEL(inputImage); 27 | //vec4 stalePixel = IMG_THIS_PIXEL(bufferVariableNameA); 28 | vec4 red = vec4(1.0, 0.0, 0.0, 1.0); 29 | vec4 green = vec4(0.0, 1.0, 0.0, 1.0); 30 | bufferVariableNameA = red; 31 | bufferVariableNameB = green; 32 | gl_FragColor = freshPixel; 33 | } 34 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/Test-Long.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of long-type inputs as pop-up buttons to display either the red, green, or blue channel of an image", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | }, 12 | { 13 | "NAME": "longInputIsPopUpButton", 14 | "VALUES": [ 15 | 0, 16 | 1, 17 | 2 18 | ], 19 | "LABELS": [ 20 | "red", 21 | "green", 22 | "blue" 23 | ], 24 | "DEFAULT": 1, 25 | "TYPE": "long" 26 | } 27 | ] 28 | }*/ 29 | 30 | void main() 31 | { 32 | vec4 srcPixel = IMG_THIS_PIXEL(inputImage); 33 | if (longInputIsPopUpButton == 0) 34 | gl_FragColor = srcPixel.rrra; 35 | else if (longInputIsPopUpButton == 1) 36 | gl_FragColor = srcPixel.ggga; 37 | else if (longInputIsPopUpButton == 2) 38 | gl_FragColor = srcPixel.bbba; 39 | } 40 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/Test-Color.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of color-type image inputs", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | }, 12 | { 13 | "NAME": "level", 14 | "TYPE": "float", 15 | "DEFAULT": 0.5, 16 | "MIN": 0.0, 17 | "MAX": 1.0 18 | }, 19 | { 20 | "NAME": "lowColor", 21 | "TYPE": "color", 22 | "DEFAULT": [ 23 | 0.0, 24 | 0.0, 25 | 1.0, 26 | 1.0 27 | ] 28 | }, 29 | { 30 | "NAME": "highColor", 31 | "TYPE": "color", 32 | "DEFAULT": [ 33 | 1.0, 34 | 1.0, 35 | 1.0, 36 | 1.0 37 | ] 38 | } 39 | ] 40 | }*/ 41 | 42 | void main() 43 | { 44 | vec4 srcPixel = IMG_THIS_PIXEL(inputImage); 45 | vec4 dstPixel = ((srcPixel.r+srcPixel.g+srcPixel.b)/3.0>level) ? lowColor : highColor; 46 | gl_FragColor = dstPixel; 47 | } 48 | -------------------------------------------------------------------------------- /scripts/create_buffer.py: -------------------------------------------------------------------------------- 1 | #if op('GLSL'): 2 | # op('GLSL').destroy() 3 | buffer_list = [] 4 | 5 | 6 | def add_buffer(name, index, width = None, height = None): 7 | global buffer_list 8 | 9 | 10 | buffer = me.parent().create(renderselectTOP, name) 11 | 12 | buffer_list.append(name) 13 | 14 | buffer.nodeX = me.nodeX 15 | buffer.nodeY = me.nodeY - (100 * index) 16 | 17 | 18 | op('GLSL').inputConnectors[index].connect(buffer) 19 | 20 | buffer.par.top = 'GLSL' 21 | buffer.par.colorbufindex = index 22 | 23 | 24 | if width == None or height == None: 25 | return 26 | 27 | buffer.par.outputresolution = 9 28 | buffer.par.resolution1 = width 29 | buffer.par.resolution2 = height 30 | 31 | return 32 | 33 | 34 | def clear_buffers(): 35 | global buffer_list 36 | 37 | print("inside clear buffers") 38 | 39 | for i in range(len(buffer_list), 0): 40 | print("deleting ", buffer_list[i]) 41 | op(buffer_list[i]).destroy() 42 | 43 | buffer_list = [] 44 | 45 | return 46 | 47 | 48 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/_Test-TempBufferDifferingSizes.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "same as TestPersistentBufferDifferingSizes, but uses a temp buffer instead of a persistent buffer", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | } 12 | ], 13 | "PASSES": [ 14 | { 15 | "TARGET":"bufferVariableNameA", 16 | "WIDTH": "$WIDTH/16.0", 17 | "HEIGHT": "$HEIGHT/16.0" 18 | }, 19 | { 20 | "DESCRIPTION": "this empty pass is rendered at the same rez as whatever you are running the ISF filter at- the previous step rendered an image at one-sixteenth the res, so this step ensures that the output is full-size" 21 | } 22 | ] 23 | 24 | }*/ 25 | 26 | void main() 27 | { 28 | // first pass: read the "inputImage"- remember, we're drawing to the persistent buffer "bufferVariableNameA" on the first pass 29 | if (PASSINDEX == 0) { 30 | gl_FragColor = IMG_THIS_NORM_PIXEL(inputImage); 31 | } 32 | // second pass: read from "bufferVariableNameA". output looks chunky and low-res. 33 | else if (PASSINDEX == 1) { 34 | gl_FragColor = IMG_THIS_NORM_PIXEL(bufferVariableNameA); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/_Test-MultiPassRendering.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of two-pass rendering- the first pass renders to a persistent buffer which is substantially smaller than the res of the image being drawn. the second pass renders at the default requested size and scales up the image from the first pass", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | } 12 | ], 13 | "PERSISTENT_BUFFERS": [ 14 | "bufferVariableNameA" 15 | ], 16 | "PASSES": [ 17 | { 18 | "TARGET":"bufferVariableNameA", 19 | "WIDTH": "$WIDTH/16.0", 20 | "HEIGHT": "$HEIGHT/16.0" 21 | }, 22 | { 23 | 24 | } 25 | ] 26 | 27 | }*/ 28 | 29 | void main() 30 | { 31 | // first pass: read the "inputImage"- remember, we're drawing to the persistent buffer "bufferVariableNameA" on the first pass 32 | if (PASSINDEX == 0) { 33 | gl_FragColor = IMG_THIS_NORM_PIXEL(inputImage); 34 | } 35 | // second pass: read from "bufferVariableNameA". output looks chunky and low-res. 36 | else if (PASSINDEX == 1) { 37 | gl_FragColor = IMG_THIS_NORM_PIXEL(bufferVariableNameA); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/_Test-PersistentBufferDifferingSizes.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of two-pass rendering- the first pass renders to a persistent buffer which is substantially smaller than the res of the image being drawn. the second pass renders at the default requested size and scales up the image from the first pass", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | } 12 | ], 13 | "PERSISTENT_BUFFERS": [ 14 | "bufferVariableNameA" 15 | ], 16 | "PASSES": [ 17 | { 18 | "TARGET":"bufferVariableNameA", 19 | "FLOAT": true, 20 | "WIDTH": "$WIDTH/16.0", 21 | "HEIGHT": "$HEIGHT/16.0" 22 | }, 23 | { 24 | 25 | } 26 | ] 27 | 28 | }*/ 29 | 30 | void main() 31 | { 32 | // first pass: read the "inputImage"- remember, we're drawing to the persistent buffer "bufferVariableNameA" on the first pass 33 | if (PASSINDEX == 0) { 34 | gl_FragColor = IMG_THIS_NORM_PIXEL(inputImage); 35 | } 36 | // second pass: read from "bufferVariableNameA". output looks chunky and low-res. 37 | else if (PASSINDEX == 1) { 38 | gl_FragColor = IMG_THIS_NORM_PIXEL(bufferVariableNameA); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /assets/ISF tests+tutorials/Test-Sampler.fs: -------------------------------------------------------------------------------- 1 | /*{ 2 | "DESCRIPTION": "demonstrates the use of multiple image-type inputs", 3 | "CREDIT": "by zoidberg", 4 | "CATEGORIES": [ 5 | "TEST-GLSL FX" 6 | ], 7 | "INPUTS": [ 8 | { 9 | "NAME": "inputImage", 10 | "TYPE": "image" 11 | }, 12 | { 13 | "NAME": "blendImage", 14 | "TYPE": "image" 15 | } 16 | ] 17 | }*/ 18 | 19 | void main() 20 | { 21 | // these two variable declarations are functionally identical (the only difference is that THIS_PIXEL is a non-dependent texture lookup) 22 | //vec4 srcPixel = IMG_PIXEL(inputImage, gl_FragCoord.xy); // returns a vec4 with the colors of the pixel in sampler "inputImage" at (non-normalized) texture coordinates "srcCoord" 23 | //vec4 srcPixel = IMG_THIS_PIXEL(inputImage); 24 | 25 | // these two variable declarations are also identical. though they behave similarly to the above declarations in this specific filter, NORM and non-NORM pixel lookups are fundamentally different and behave differently under other circumstances. 26 | //vec4 srcPixel = IMG_NORM_PIXEL(inputImage, vv_FragNormCoord); 27 | vec4 srcPixel = IMG_THIS_NORM_PIXEL(inputImage); 28 | 29 | vec4 blendPixel = IMG_THIS_NORM_PIXEL(blendImage); // returns a vec4 with the colors of the pixel in sampler "inputImage" at (normalized) texture coordinates "blendCoord". 30 | gl_FragColor = srcPixel/2.0 + blendPixel/2.0; 31 | } 32 | -------------------------------------------------------------------------------- /scripts/find_and_replace_script_callbacks.py: -------------------------------------------------------------------------------- 1 | # me is this DAT. 2 | # 3 | # scriptOP is the OP which is cooking. 4 | 5 | def cook(scriptOP): 6 | scriptOP.clear() 7 | 8 | text = op('shader_out').text 9 | total_int = len(text) 10 | 11 | #scriptOP.write("#total length = ", total_int) 12 | 13 | 14 | #insert vUV in the appropriate place if IMG_THIS_PIXEL is found 15 | start_int = 0 16 | found_int = text.find("IMG_THIS_PIXEL(", start_int) 17 | while found_int > 0: 18 | #scriptOP.write("IMG_THIS_PIXEL( found at: ", found_int, "\n") 19 | found_int = text.find( ");", found_int ) 20 | #scriptOP.write("); found at: ", found_int) 21 | hashlist = list(text) 22 | hashlist.insert(found_int, ", vUV.st") 23 | text = ''.join(hashlist) 24 | 25 | start_int = found_int 26 | found_int = text.find("IMG_THIS_PIXEL(", start_int) 27 | 28 | 29 | #insert vUV in the appropriate place if IMG_THIS_NORM_PIXEL is found 30 | start_int = 0 31 | found_int = text.find("IMG_THIS_NORM_PIXEL(", start_int) 32 | while found_int > 0: 33 | #scriptOP.write("IMG_THIS_PIXEL( found at: ", found_int, "\n") 34 | found_int = text.find( ");", found_int ) 35 | #scriptOP.write("); found at: ", found_int) 36 | hashlist = list(text) 37 | hashlist.insert(found_int, ", vUV.st") 38 | text = ''.join(hashlist) 39 | 40 | start_int = found_int 41 | found_int = text.find("IMG_THIS_PIXEL(", start_int) 42 | 43 | 44 | 45 | text = text.replace("IMG_THIS_PIXEL", "texture") 46 | text = text.replace("IMG_THIS_NORM_PIXEL", "texture") 47 | text = text.replace("IMG_PIXEL", "texture") 48 | text = text.replace("IMG_NORM_PIXEL", "texture") 49 | text = text.replace("PASSINDEX", "uTDPass") 50 | 51 | 52 | 53 | 54 | #make this dynamic 55 | text = text.replace("inputImage", "sTD2DInputs[0]") 56 | 57 | 58 | text = text.replace("gl_FragColor", "fragColor") 59 | 60 | 61 | text = text.replace("vv_FragNormCoord", "vUV.st") 62 | #text = text.replace("vv_FragNormCoord", "vec2(vUV.s, vUV.t / 2.0)") 63 | text = text.replace("gl_FragCoord.xy", "vUV.st") 64 | 65 | scriptOP.write(text) 66 | 67 | 68 | 69 | return 70 | -------------------------------------------------------------------------------- /scripts/json_parser_script_callbacks.py: -------------------------------------------------------------------------------- 1 | import json 2 | import uniform_maker 3 | 4 | 5 | 6 | def cook(scriptOP): 7 | 8 | op('create_glop').run() 9 | print("running clear buffers") 10 | uniform_maker.clearBuffers() 11 | 12 | 13 | scriptOP.clear() 14 | headertext = op( 'header_out' ).text 15 | header_dict = json.loads(headertext) 16 | dict_len = len(header_dict) 17 | 18 | ph = op('parsed_header') 19 | ph.clear() 20 | uniform_maker.reset_current_uniform() 21 | 22 | 23 | 24 | #op('res')[0,0] = eval(op('in1').width) 25 | #op('res')[0,1] = eval(op('in1').height) 26 | #me.parent().store('width', op('in1').width) 27 | #me.parent().store('height', op('in1').height) 28 | 29 | 30 | #meta 31 | if "DESCRIPTION" in header_dict: 32 | description = header_dict["DESCRIPTION"] 33 | #scriptOP.write("description: ", description, '\n') 34 | op('META')[0,0] = description 35 | ph.write("//DESCRIPTION: ", description, "\n") 36 | 37 | if "CREDIT" in header_dict: 38 | credit = header_dict["CREDIT"] 39 | #scriptOP.write("credit: ", credit, '\n') 40 | op('META')[0,1] = credit 41 | ph.write("//CREDIT: ", credit, "\n") 42 | 43 | #scriptOP.write("\n\n") 44 | 45 | #categories 46 | category_list = header_dict["CATEGORIES"] 47 | num_categories = len(category_list) 48 | #scriptOP.write("number of categories: ", num_categories, '\n') 49 | ph.write("//Categories: ") 50 | 51 | for i in range (0,num_categories): 52 | ph.write(category_list[i]) 53 | if i + 1 < num_categories: 54 | ph.write(", ") 55 | 56 | #scriptOP.write("category ", i, ": ", category_list[i], '\n') 57 | 58 | ph.write("\n\n") 59 | 60 | ph.write("uniform float TIME;\n") 61 | ph.write("uniform int PASSINDEX;\n") 62 | ph.write("uniform vec2 RENDERSIZE;\n") 63 | 64 | uniform_maker.make_generic_uniforms() 65 | 66 | ph.write("varying vec2 vv_FragNormCoord;\n") 67 | ph.write("varying vec3 vv_VertNorm;\n") 68 | ph.write("varying vec3 vv_VertPos;\n") 69 | 70 | ph.write("\n") 71 | 72 | op('META')[0,2] = category_list 73 | 74 | #scriptOP.write("\n\n") 75 | 76 | 77 | 78 | 79 | 80 | 81 | #inputs 82 | num_inputs = len(header_dict["INPUTS"]) 83 | #scriptOP.write("number of inputs: ", num_inputs, "\n") 84 | 85 | for i in range(0,num_inputs): 86 | input_keys = header_dict["INPUTS"][i].keys() 87 | #scriptOP.write(header_dict["INPUTS"][i]["TYPE"], "\n") 88 | 89 | if header_dict["INPUTS"][i]["TYPE"] == "float": 90 | uniform_maker.uFloat( header_dict["INPUTS"][i] ) 91 | 92 | 93 | if header_dict["INPUTS"][i]["TYPE"] == "int": 94 | uniform_maker.uInt( header_dict["INPUTS"][i] ) 95 | 96 | if header_dict["INPUTS"][i]["TYPE"] == "bool": 97 | uniform_maker.uBool( header_dict["INPUTS"][i] ) 98 | 99 | 100 | if header_dict["INPUTS"][i]["TYPE"] == "event": 101 | uniform_maker.uEvent( header_dict["INPUTS"][i] ) 102 | 103 | if header_dict["INPUTS"][i]["TYPE"] == "long": 104 | uniform_maker.uLong( header_dict["INPUTS"][i] ) 105 | 106 | 107 | if header_dict["INPUTS"][i]["TYPE"] == "point2D": 108 | uniform_maker.uPoint2D( header_dict["INPUTS"][i] ) 109 | 110 | if header_dict["INPUTS"][i]["TYPE"] == "color": 111 | uniform_maker.uColor( header_dict["INPUTS"][i] ) 112 | 113 | 114 | if header_dict["INPUTS"][i]["TYPE"] == "image": 115 | uniform_maker.uImage( header_dict["INPUTS"][i] ) 116 | 117 | # scriptOP.write( "input ", i, "\n") 118 | # for j in range(0,len(input_keys)): 119 | # key = list(input_keys)[j] 120 | # value = header_dict["INPUTS"][i][key] 121 | # scriptOP.write("\t\t", key, ": ", value, "\n") 122 | 123 | #scriptOP.write("\n") 124 | 125 | #scriptOP.write("\n") 126 | 127 | 128 | 129 | #passes 130 | #TODO if a pass has a key TARGET, that is the buffer to render in that pass 131 | #if it is not a persistent buffer, a temporary one is created and dies each frame 132 | # if "PASSES" in header_dict: 133 | # num_passes = len(header_dict["PASSES"]) 134 | # scriptOP.write("number of passes: ", num_passes, "\n") 135 | 136 | # for i in range(0,num_passes): 137 | # input_keys = header_dict["PASSES"][i].keys() 138 | 139 | # #if name key exists, make uniform 140 | # if "NAME" in header_dict["PASSES"][i]: 141 | # uniform_maker.uImage( header_dict["PASSES"][i] ) 142 | 143 | # scriptOP.write( "pass ", i, "\n") 144 | # for j in range(0,len(input_keys)): 145 | # key = list(input_keys)[j] 146 | # value = header_dict["PASSES"][i][key] 147 | # scriptOP.write("\t\t", key, ": ", value, "\n") 148 | 149 | # scriptOP.write("\n") 150 | 151 | # scriptOP.write("\n") 152 | 153 | 154 | 155 | 156 | 157 | uniform_maker.uDefaultBuffer() 158 | 159 | 160 | 161 | 162 | #persistent buffers 163 | #could be a an array of strings (names) or a dict with width and height keys 164 | #TODO: check for string or dict 165 | #!!!may or may not have keys 166 | #this is causing errors when there are no keys 167 | if "PERSISTENT_BUFFERS" in header_dict: 168 | 169 | #check is string or dict 170 | 171 | buffer_list = header_dict["PERSISTENT_BUFFERS"] 172 | num_buffers = len(buffer_list) 173 | scriptOP.write("number of persistent buffers: ", num_buffers, "\n") 174 | 175 | 176 | if isinstance(buffer_list[0], str): 177 | scriptOP.write("STRING!\n") 178 | for i in range(0, num_buffers): 179 | uniform_maker.uBuffer(buffer_list[i]) 180 | 181 | 182 | 183 | 184 | 185 | #check for dict 186 | if isinstance(buffer_list[0], dict): 187 | scriptOP.write("DICT!\n") 188 | 189 | 190 | 191 | 192 | 193 | 194 | # buffer_keys = header_dict["PERSISTENT_BUFFERS"].keys() 195 | 196 | 197 | # for i in range(0,num_buffers): 198 | # buffer_key = list(buffer_keys)[i] 199 | # this_buffer = header_dict["PERSISTENT_BUFFERS"][buffer_key] 200 | # num_buffer_items = len(this_buffer) 201 | # scriptOP.write( "buffer ", i, "\n") 202 | # scriptOP.write( "\t\t", buffer_key , "\n") 203 | 204 | # for j in range(0,num_buffer_items): 205 | # key = list(this_buffer)[j] 206 | # value = this_buffer[key] 207 | # scriptOP.write("\t\t", key, ": ", value, "\n") 208 | 209 | scriptOP.write("\n") 210 | 211 | scriptOP.write("\n\n") 212 | 213 | 214 | #may need to check for a name key, if doesn't exist use key for dictionary 215 | if "IMPORTED" in header_dict: 216 | import_dict = header_dict["IMPORTED"] 217 | num_imports = len(import_dict) 218 | scriptOP.write("number of imports: ", num_imports, "\n") 219 | import_keys = import_dict.keys() 220 | 221 | for i in range(0,num_imports): 222 | import_key = list(import_keys)[i] 223 | this_import = import_dict[import_key] 224 | num_buffer_items = len(this_import) 225 | scriptOP.write("import ", i, "\n") 226 | scriptOP.write( "\t\t", import_key , "\n") 227 | 228 | for j in range(0,num_buffer_items): 229 | key = list(this_import)[j] 230 | value =this_import[key] 231 | scriptOP.write("\t\t", key, ": ", value, "\n") 232 | 233 | scriptOP.write("\n") 234 | 235 | scriptOP.write("\n\n") 236 | 237 | 238 | #set number of color buffers in glop 239 | uniform_maker.set_glop_buf_num() 240 | 241 | 242 | 243 | return 244 | 245 | 246 | -------------------------------------------------------------------------------- /scripts/uniform_maker.py: -------------------------------------------------------------------------------- 1 | import create_buffer 2 | 3 | glop = op('GLSL') 4 | current_uniform = 0 5 | current_buffer = 0 6 | resx = 1280 7 | resy = 720 8 | 9 | def reset_current_uniform(): 10 | global current_uniform 11 | current_uniform = 0 12 | current_buffer = 0 13 | return 14 | 15 | 16 | def set_glop_buf_num(): 17 | print( "setting number of color buffers: ", current_buffer) 18 | op('GLSL').par.numcolorbufs.val = current_buffer 19 | return 20 | 21 | 22 | 23 | def make_generic_uniforms(): 24 | global current_uniform 25 | 26 | current_uniform = 0 27 | 28 | glop = op('GLSL') 29 | 30 | #make TIME 31 | uni = "uniname" + str(current_uniform) 32 | setattr(glop.par, uni, "TIME") 33 | val = "value" + str(current_uniform) + "x" 34 | #setattr(glop.expr, val, "me.time.absSeconds") 35 | #THIS IS HACKY 36 | glop.par.value0x.expr = "me.time.absSeconds" 37 | 38 | current_uniform += 1 39 | 40 | #make RENDERSIZE 41 | uni = "uniname" + str(current_uniform) 42 | setattr(glop.par, uni, "RENDERSIZE") 43 | val = "value" + str(current_uniform) + "x" 44 | setattr(glop.par, val, resx) 45 | val = "value" + str(current_uniform) + "y" 46 | setattr(glop.par, val, resy) 47 | current_uniform += 1 48 | 49 | 50 | 51 | 52 | def uFloat( data ): 53 | global current_uniform 54 | 55 | #get name 56 | name = data["NAME"] 57 | #write uniform to shader 58 | op('parsed_header').write( "uniform float ", name, ";\n" ) 59 | #set uniform in operator 60 | uni = "uniname" + str(current_uniform) 61 | setattr(glop.par, uni, name) 62 | 63 | 64 | #check for and get default 65 | if "DEFAULT" in data: 66 | default = data["DEFAULT"] 67 | val = "value" + str(current_uniform) + "x" 68 | setattr(glop.par, val , default) 69 | 70 | 71 | #get min 72 | #get max 73 | #get label 74 | #get identity 75 | 76 | current_uniform += 1 77 | return 78 | 79 | 80 | 81 | 82 | # NO INT IN ISF SPEC? 83 | def uInt( data ): 84 | op('parsed_header').write( "uniform int ", data["NAME"], ";\n" ) 85 | #get min 86 | #get max 87 | #get default 88 | #get label 89 | #get identity 90 | return 91 | 92 | 93 | 94 | 95 | def uBool( data ): 96 | global current_uniform 97 | 98 | #get name 99 | name = data["NAME"] 100 | #write uniform to shader 101 | op('parsed_header').write( "uniform bool ", name, ";\n" ) 102 | #set uniform in operator 103 | uni = "uniname" + str(current_uniform) 104 | setattr(glop.par, uni, name) 105 | 106 | 107 | #check for and get default 108 | if "DEFAULT" in data: 109 | default = data["DEFAULT"] 110 | val = "value" + str(current_uniform) + "x" 111 | setattr(glop.par, val , default) 112 | 113 | #get min 114 | #get max 115 | #get label 116 | #get identity 117 | 118 | current_uniform += 1 119 | return 120 | 121 | 122 | 123 | 124 | def uEvent( data ): 125 | global current_uniform 126 | 127 | #get name 128 | name = data["NAME"] 129 | #write uniform to shader 130 | op('parsed_header').write( "uniform bool ", name, ";\n" ) 131 | #set uniform in operator 132 | uni = "uniname" + str(current_uniform) 133 | setattr(glop.par, uni, name) 134 | 135 | 136 | #check for and get default 137 | if "DEFAULT" in data: 138 | default = data["DEFAULT"] 139 | val = "value" + str(current_uniform) + "x" 140 | setattr(glop.par, val , default) 141 | else: 142 | val = "value" + str(current_uniform) + "x" 143 | setattr(glop.par, val , 0) 144 | 145 | #get min 146 | #get max 147 | #get label 148 | #get identity 149 | 150 | current_uniform += 1 151 | return 152 | 153 | 154 | 155 | 156 | 157 | #TODO - how to handle these? 158 | 159 | def uLong( data ): 160 | global current_uniform 161 | 162 | #get name 163 | name = data["NAME"] 164 | #write uniform to shader 165 | op('parsed_header').write( "uniform int ", data["NAME"], ";\n" ) 166 | #set uniform in operator 167 | uni = "uniname" + str(current_uniform) 168 | setattr(glop.par, uni, name) 169 | 170 | 171 | #check for and get default 172 | if "DEFAULT" in data: 173 | default = data["DEFAULT"] 174 | val = "value" + str(current_uniform) + "x" 175 | setattr(glop.par, val , default) 176 | 177 | 178 | #get min 179 | #get max 180 | #get default 181 | #get label 182 | #get identity 183 | #get VALUES 184 | #get LABELS 185 | current_uniform += 1 186 | return 187 | 188 | 189 | 190 | 191 | 192 | def uPoint2D( data ): 193 | global current_uniform 194 | 195 | #get name 196 | name = data["NAME"] 197 | #write uniform to shader 198 | op('parsed_header').write( "uniform vec2 ", data["NAME"], ";\n" ) 199 | #set uniform in operator 200 | uni = "uniname" + str(current_uniform) 201 | setattr(glop.par, uni, name) 202 | 203 | 204 | #check for and get default 205 | if "DEFAULT" in data: 206 | default = data["DEFAULT"] 207 | val = "value" + str(current_uniform) + "x" 208 | setattr(glop.par, val , default[0]) 209 | val = "value" + str(current_uniform) + "y" 210 | setattr(glop.par, val , default[1]) 211 | 212 | #get min 213 | #get max 214 | #get label 215 | #get identity 216 | 217 | current_uniform += 1 218 | return 219 | 220 | 221 | 222 | 223 | def uColor( data ): 224 | global current_uniform 225 | 226 | #get name 227 | name = data["NAME"] 228 | #write uniform to shader 229 | op('parsed_header').write( "uniform vec4 ", data["NAME"], ";\n" ) 230 | #set uniform in operator 231 | uni = "uniname" + str(current_uniform) 232 | setattr(glop.par, uni, name) 233 | 234 | 235 | #check for and get default 236 | if "DEFAULT" in data: 237 | default = data["DEFAULT"] 238 | val = "value" + str(current_uniform) + "x" 239 | setattr(glop.par, val , default[0]) 240 | val = "value" + str(current_uniform) + "y" 241 | setattr(glop.par, val , default[1]) 242 | val = "value" + str(current_uniform) + "z" 243 | setattr(glop.par, val , default[2]) 244 | val = "value" + str(current_uniform) + "w" 245 | setattr(glop.par, val , default[3]) 246 | 247 | #get min 248 | #get max 249 | #get label 250 | #get identity 251 | 252 | current_uniform += 1 253 | return 254 | 255 | 256 | 257 | def uImage( data ): 258 | #TODO - how to handle these? 259 | #op('parsed_header').write( "uniform sampler2DRect ", data["NAME"], ";\n" ) 260 | # op('parsed_header').write( "uniform vec4 _", data["NAME"], "_imgRect;\n" ) 261 | # op('parsed_header').write( "uniform vec2 _", data["NAME"], "_imgSize;\n" ) 262 | # op('parsed_header').write( "uniform bool _", data["NAME"], "_flip;\n" ) 263 | # op('parsed_header').write( "varying vec2 _", data["NAME"], "_texCoord;\n" ) 264 | op('parsed_header').write( "\n" ) 265 | 266 | #get min 267 | #get max 268 | #get default 269 | #get label 270 | #get identity 271 | return 272 | 273 | 274 | 275 | 276 | def uDefaultBuffer(): 277 | global current_buffer 278 | 279 | current_buffer = 0 280 | 281 | op('parsed_header').write("layout (location = ", current_buffer, ") out vec4 fragColor;") 282 | op('parsed_header').write( "\n" ) 283 | print("adding buffer #:", current_buffer) 284 | 285 | current_buffer += 1 286 | return 287 | 288 | 289 | 290 | def uBuffer( nameString ): 291 | global current_buffer 292 | 293 | #write output location to header 294 | op('parsed_header').write("layout (location = ", current_buffer, ") out vec4 ", nameString,";") 295 | op('parsed_header').write( "\n" ) 296 | 297 | #create buffer 298 | 299 | create_buffer.add_buffer(nameString, current_buffer) 300 | 301 | current_buffer += 1 302 | return 303 | 304 | 305 | def uBufferDict( buffer_dict ): 306 | return 307 | 308 | 309 | def clearBuffers(): 310 | create_buffer.clear_buffers() 311 | return --------------------------------------------------------------------------------